Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptMoveGenerator.cs	(revision 3074)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/StochasticThreeOptMoveGenerator.cs	(revision 3200)
@@ -30,10 +30,10 @@
   [Item("StochasticThreeOptMoveGenerator", "Randomly samples n from all possible 3-opt moves from a given permutation.")]
   [StorableClass]
-  public class StochasticThreeOptMoveGenerator : ThreeOptMoveGenerator, IStochasticOperator {
+  public class StochasticThreeOptMultiMoveGenerator : ThreeOptMoveGenerator, IStochasticOperator, IMultiMoveGenerator {
     public ILookupParameter<IRandom> RandomParameter {
       get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
     }
-    private ValueLookupParameter<IntValue> SampleSizeParameter {
-      get { return (ValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
     }
 
@@ -43,5 +43,5 @@
     }
 
-    public StochasticThreeOptMoveGenerator()
+    public StochasticThreeOptMultiMoveGenerator()
       : base() {
       Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
@@ -51,18 +51,14 @@
     public static ThreeOptMove[] Apply(Permutation permutation, IRandom random, int sampleSize) {
       int length = permutation.Length;
-      /*int totalMoves = (length) * (length - 1) / 2 - 3;
-      // FIXME: Remove this comment if ExhaustiveThreeOptMoveGenerator exists, otherwise alter the exception message below.
-      if (sampleSize >= totalMoves) throw new InvalidOperationException("StochasticThreeOptMoveGenerator: Sample size (" + sampleSize + ") is larger than the set of all possible moves (" + totalMoves + "), use the ExhaustiveThreeOptMoveGenerator instead.");
-      */
       ThreeOptMove[] moves = new ThreeOptMove[sampleSize];
       for (int i = 0; i < sampleSize; i++) {
         int index1, index2, index3;
-        do {
-          index1 = random.Next(length - 1);
-          index2 = random.Next(index1 + 1, length);
-        } while (index2 - index1 == length - 1);
-        do {
-          index3 = random.Next(length);
-        } while (index1 <= index3 && index3 <= index2 + 1);
+        index1 = random.Next(length - 1);
+        index2 = random.Next(index1 + 1, length);
+        index3 = length - index2 + index1 - 1;  // get insertion point in remaining part
+        if (index3 > 0)
+          index3 = random.Next(index3);
+        else
+          index3 = 0;
         moves[i] = new ThreeOptMove(index1, index2, index3);
       }
Index: trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveMaker.cs	(revision 3200)
+++ trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/ThreeOpt/ThreeOptMoveMaker.cs	(revision 3200)
@@ -0,0 +1,71 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("ThreeOptMoveMaker", "Peforms a 3-opt move on a given permutation and updates the quality.")]
+  [StorableClass]
+  public class ThreeOptMoveMaker : SingleSuccessorOperator, IThreeOptPermutationMoveOperator, IMoveMaker {
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<ThreeOptMove> ThreeOptMoveParameter {
+      get { return (ILookupParameter<ThreeOptMove>)Parameters["ThreeOptMove"]; }
+    }
+    public ILookupParameter<Permutation> PermutationParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+
+    public ThreeOptMoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<ThreeOptMove>("ThreeOptMove", "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 IOperation Apply() {
+      ThreeOptMove move = ThreeOptMoveParameter.ActualValue;
+      Permutation permutation = PermutationParameter.ActualValue;
+      DoubleValue moveQuality = MoveQualityParameter.ActualValue;
+      DoubleValue quality = QualityParameter.ActualValue;
+
+      TranslocationManipulator.Apply(permutation, move.Index1, move.Index2, move.Index3);
+      quality.Value = moveQuality.Value;
+
+      return base.Apply();
+    }
+
+    public override bool CanChangeName {
+      get { return false; }
+    }
+  }
+}
