Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/BiasedModelTrainer.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/BiasedModelTrainer.cs	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/BiasedModelTrainer.cs	(revision 14776)
@@ -26,4 +26,5 @@
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Encodings.BinaryVectorEncoding.SolutionModel;
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
@@ -31,4 +32,6 @@
 
 namespace HeuristicLab.Algorithms.MemPR.Binary.SolutionModel.Univariate {
+  public enum ModelBiasOptions { Rank, Fitness }
+
   [Item("Biased Univariate Model Trainer (binary)", "", ExcludeGenericTypeInfo = true)]
   [StorableClass]
@@ -60,5 +63,17 @@
 
     public void TrainModel(TContext context) {
-      context.Model = Trainer.TrainBiased(ModelBias, context.Random, context.Maximization, context.Population.Select(x => x.Solution), context.Population.Select(x => x.Fitness));
+      var biasType = modelBiasParameter.Value.Value;
+      switch (biasType) {
+        case ModelBiasOptions.Fitness:
+          context.Model = UnivariateModelTrainer.TrainWithFitnessBias(context.Random, context.Maximization,
+            context.Population.Select(x => x.Solution),
+            context.Population.Select(x => x.Fitness));
+          break;
+        case ModelBiasOptions.Rank:
+          context.Model = UnivariateModelTrainer.TrainWithRankBias(context.Random, context.Maximization,
+            context.Population.Select(x => x.Solution),
+            context.Population.Select(x => x.Fitness));
+          break;
+      }
     }
   }
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnbiasedModelTrainer.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnbiasedModelTrainer.cs	(revision 14776)
@@ -25,4 +25,5 @@
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Encodings.BinaryVectorEncoding.SolutionModel;
 using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -49,5 +50,5 @@
 
     public void TrainModel(TContext context) {
-      context.Model = Trainer.TrainUnbiased(context.Random, context.Population.Select(x => x.Solution));
+      context.Model = UnivariateModelTrainer.TrainUnbiased(context.Random, context.Population.Select(x => x.Solution));
     }
   }
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnivariateSolutionModel.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Binary/SolutionModel/Univariate/UnivariateSolutionModel.cs	(revision 14695)
+++ 	(revision )
@@ -1,125 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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 System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Algorithms.MemPR.Interfaces;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Encodings.BinaryVectorEncoding;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Random;
-
-namespace HeuristicLab.Algorithms.MemPR.Binary.SolutionModel.Univariate {
-  [Item("Univariate solution model (binary)", "")]
-  [StorableClass]
-  public sealed class UnivariateModel : Item, ISolutionModel<BinaryVector> {
-    [Storable]
-    public DoubleArray Probabilities { get; set; }
-    [Storable]
-    public IRandom Random { get; set; }
-
-    [StorableConstructor]
-    private UnivariateModel(bool deserializing) : base(deserializing) { }
-    private UnivariateModel(UnivariateModel original, Cloner cloner)
-      : base(original, cloner) {
-      Probabilities = cloner.Clone(original.Probabilities);
-      Random = cloner.Clone(original.Random);
-    }
-    public UnivariateModel(IRandom random, int N) : this(random, Enumerable.Range(0, N).Select(x => 0.5).ToArray()) { }
-    public UnivariateModel(IRandom random, double[] probabilities) {
-      Probabilities = new DoubleArray(probabilities);
-      Random = random;
-    }
-    public UnivariateModel(IRandom random, DoubleArray probabilties) {
-      Probabilities = probabilties;
-      Random = random;
-    }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new UnivariateModel(this, cloner);
-    }
-
-    public BinaryVector Sample() {
-      var vec = new BinaryVector(Probabilities.Length);
-      for (var i = 0; i < Probabilities.Length; i++)
-        vec[i] = Random.NextDouble() < Probabilities[i];
-      return vec;
-    }
-
-    public static ISolutionModel<BinaryVector> CreateWithoutBias(IRandom random, IEnumerable<BinaryVector> population) {
-      double[] model = null;
-      var popSize = 0;
-      foreach (var p in population) {
-        popSize++;
-        if (model == null) model = new double[p.Length];
-        for (var x = 0; x < model.Length; x++) {
-          if (p[x]) model[x]++;
-        }
-      }
-      if (model == null) throw new ArgumentException("Cannot train model from empty population.");
-      // normalize to [0;1]
-      var factor = 1.0 / popSize;
-      for (var x = 0; x < model.Length; x++) {
-        model[x] *= factor;
-      }
-      return new UnivariateModel(random, model);
-    }
-
-    public static ISolutionModel<BinaryVector> CreateWithRankBias(IRandom random, bool maximization, IEnumerable<BinaryVector> population, IEnumerable<double> qualities) {
-      var popSize = 0;
-
-      double[] model = null;
-      var pop = population.Zip(qualities, (b, q) => new { Solution = b, Fitness = q });
-      foreach (var ind in maximization ? pop.OrderBy(x => x.Fitness) : pop.OrderByDescending(x => x.Fitness)) {
-        // from worst to best, worst solution has 1 vote, best solution N votes
-        popSize++;
-        if (model == null) model = new double[ind.Solution.Length];
-        for (var x = 0; x < model.Length; x++) {
-          if (ind.Solution[x]) model[x] += popSize;
-        }
-      }
-      if (model == null) throw new ArgumentException("Cannot train model from empty population.");
-      // normalize to [0;1]
-      var factor = 2.0 / (popSize + 1);
-      for (var i = 0; i < model.Length; i++) {
-        model[i] *= factor / popSize;
-      }
-      return new UnivariateModel(random, model);
-    }
-
-    public static ISolutionModel<BinaryVector> CreateWithFitnessBias(IRandom random, bool maximization, IEnumerable<BinaryVector> population, IEnumerable<double> qualities) {
-      var proportions = Util.Auxiliary.PrepareProportional(qualities, true, !maximization);
-      var factor = 1.0 / proportions.Sum();
-      double[] model = null;
-      foreach (var ind in population.Zip(proportions, (p, q) => new { Solution = p, Proportion = q })) {
-        if (model == null) model = new double[ind.Solution.Length];
-        for (var x = 0; x < model.Length; x++) {
-          if (ind.Solution[x]) model[x] += ind.Proportion * factor;
-        }
-      }
-      if (model == null) throw new ArgumentException("Cannot train model from empty population.");
-      return new UnivariateModel(random, model);
-    }
-  }
-}
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/HeuristicLab.Algorithms.MemPR-3.3.csproj
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/HeuristicLab.Algorithms.MemPR-3.3.csproj	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/HeuristicLab.Algorithms.MemPR-3.3.csproj	(revision 14776)
@@ -102,12 +102,4 @@
       <Private>False</Private>
     </Reference>
-    <Reference Include="HeuristicLab.Encodings.BinaryVectorEncoding-3.3">
-      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Encodings.BinaryVectorEncoding-3.3.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4">
-      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
     <Reference Include="HeuristicLab.Operators-3.3">
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Operators-3.3.dll</HintPath>
@@ -165,6 +157,4 @@
     <Compile Include="Binary\LocalSearch\ExhaustiveBitflip.cs" />
     <Compile Include="Binary\LocalSearch\StaticAPI\ExhaustiveBitflip.cs" />
-    <Compile Include="Binary\SolutionModel\Univariate\StaticAPI\Trainer.cs" />
-    <Compile Include="Binary\SolutionModel\Univariate\UnivariateSolutionModel.cs" />
     <Compile Include="Binary\SolutionModel\Univariate\BiasedModelTrainer.cs" />
     <Compile Include="Binary\SolutionModel\Univariate\UnbiasedModelTrainer.cs" />
@@ -179,4 +169,6 @@
     <Compile Include="LinearLinkage\SolutionModel\Univariate\UnivariateSolutionModel.cs" />
     <Compile Include="MemPRAlgorithm.cs" />
+    <Compile Include="Permutation\InversionPathRelinker.cs" />
+    <Compile Include="Permutation\LocalSearch\ExhaustiveInversionImprover.cs" />
     <Compile Include="Permutation\PermutationMemPR.cs" />
     <Compile Include="Permutation\PermutationMemPRContext.cs" />
@@ -212,4 +204,14 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.BinaryVectorEncoding\3.3\HeuristicLab.Encodings.BinaryVectorEncoding-3.3.csproj">
+      <Project>{66d249c3-a01d-42a8-82a2-919bc8ec3d83}</Project>
+      <Name>HeuristicLab.Encodings.BinaryVectorEncoding-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.LinearLinkageEncoding\3.4\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj">
+      <Project>{be698769-975a-429e-828c-72bb2b6182c8}</Project>
+      <Name>HeuristicLab.Encodings.LinearLinkageEncoding-3.4</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Encodings.PermutationEncoding\3.3\HeuristicLab.Encodings.PermutationEncoding-3.3.csproj">
       <Project>{dbecb8b0-b166-4133-baf1-ed67c3fd7fca}</Project>
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Interfaces/Interfaces.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Interfaces/Interfaces.cs	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Interfaces/Interfaces.cs	(revision 14776)
@@ -37,8 +37,4 @@
    * ********************************************* *
    *************************************************/
-
-  public interface ISolutionModel<TSolution> : IItem {
-    TSolution Sample();
-  }
 
   public interface ISolutionSubspace<TSolution> : IItem { }
@@ -89,4 +85,5 @@
       where TProblem : class, ISingleObjectiveHeuristicOptimizationProblem {
     IEnumerable<ISingleObjectiveSolutionScope<TSolution>> Population { get; }
+    int PopulationCount { get; }
   }
 
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/StaticAPI/Trainer.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/StaticAPI/Trainer.cs	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/StaticAPI/Trainer.cs	(revision 14776)
@@ -21,7 +21,7 @@
 
 using System.Collections.Generic;
-using HeuristicLab.Algorithms.MemPR.Interfaces;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.LinearLinkageEncoding;
+using HeuristicLab.Optimization;
 
 namespace HeuristicLab.Algorithms.MemPR.Grouping.SolutionModel.Univariate {
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/UnivariateSolutionModel.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/UnivariateSolutionModel.cs	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/SolutionModel/Univariate/UnivariateSolutionModel.cs	(revision 14776)
@@ -22,9 +22,9 @@
 using System;
 using System.Collections.Generic;
-using HeuristicLab.Algorithms.MemPR.Interfaces;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.LinearLinkageEncoding;
+using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/InversionPathRelinker.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/InversionPathRelinker.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/InversionPathRelinker.cs	(revision 14776)
@@ -0,0 +1,187 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Remoting.Contexts;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.TravelingSalesman {
+  [Item("InversionPathRelinker", "An operator that relinks solutions.")]
+  [StorableClass]
+  public sealed class InversionPathRelinker : SingleObjectivePathRelinker, IStochasticOperator {
+    public IValueLookupParameter<DoubleMatrix> DistanceMatrixParameter {
+      get { return (IValueLookupParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
+    }
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>) Parameters["Random"]; }
+    }
+    [StorableConstructor]
+    private InversionPathRelinker(bool deserializing) : base(deserializing) { }
+    private InversionPathRelinker(InversionPathRelinker original, Cloner cloner) : base(original, cloner) { }
+
+    public InversionPathRelinker() : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("DistanceMatrix"));
+      Parameters.Add(new LookupParameter<IRandom>("Random"));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InversionPathRelinker(this, cloner);
+    }
+
+    protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
+      if (parents.Length != 2)
+        throw new ArgumentException("The number of parents is not equal to 2.");
+      var random = RandomParameter.ActualValue;
+      var distances = DistanceMatrixParameter.ActualValue;
+      Func<Permutation, double> eval = (p) => {
+        double length = 0;
+        for (int i = 0; i < p.Length - 1; i++)
+          length += distances[p[i], p[i + 1]];
+        length += distances[p[p.Length - 1], p[0]];
+        return length;
+      };
+      return new ItemArray<IItem>(RelinkOpt(random, (Permutation)parents[0],
+        (Permutation)parents[1], eval));
+    }
+
+    public IEnumerable<Permutation> RelinkOpt(IRandom random, Permutation p1, Permutation p2,
+                               Func<Permutation, double> eval) {
+
+      var evaluations = 0;
+      var child = (Permutation)p1.Clone();
+      
+      Permutation bestChild = null;
+
+      var invChild = new int[child.Length];
+      var invP2 = new int[child.Length];
+      for (var i = 0; i < child.Length; i++) {
+        invChild[child[i]] = i;
+        invP2[p2[i]] = i;
+      }
+
+      var bestChange = double.NaN;
+      var moveQueue = new Queue<Tuple<int, int>>();
+      var undoStack = new Stack<Tuple<int, int>>();
+      do {
+        Queue<Tuple<int, int>> bestQueue = null;
+        bestChange = double.NaN;
+        for (var j = 0; j < p2.Length; j++) {
+          if (IsUndirectedEdge(invChild, p2[j], p2.GetCircular(j + 1))) continue;
+
+          var a = invChild[p2[j]];
+          var b = invChild[p2.GetCircular(j + 1)];
+          if (a > b) { var h = a; a = b; b = h; }
+          var aprev = a - 1;
+          var bprev = b - 1;
+          while (IsUndirectedEdge(invP2, child.GetCircular(aprev), child.GetCircular(aprev + 1))) {
+            aprev--;
+          }
+          while (IsUndirectedEdge(invP2, child.GetCircular(bprev), child.GetCircular(bprev + 1))) {
+            bprev--;
+          }
+          var bnext = b + 1;
+          var anext = a + 1;
+          while (IsUndirectedEdge(invP2, child.GetCircular(bnext - 1), child.GetCircular(bnext))) {
+            bnext++;
+          }
+          while (IsUndirectedEdge(invP2, child.GetCircular(anext - 1), child.GetCircular(anext))) {
+            anext++;
+          }
+          aprev++; bprev++; anext--; bnext--;
+
+          if (aprev < a && bnext > b) {
+            if (aprev < 0) {
+              moveQueue.Enqueue(Tuple.Create(a + 1, bnext));
+              moveQueue.Enqueue(Tuple.Create(a + 1, a + 1 + (bnext - b)));
+            } else {
+              moveQueue.Enqueue(Tuple.Create(aprev, b - 1));
+              moveQueue.Enqueue(Tuple.Create(b - 1 - (a - aprev), b - 1));
+            }
+          } else if (aprev < a && bnext == b && bprev == b) {
+            moveQueue.Enqueue(Tuple.Create(a + 1, b));
+          } else if (aprev < a && bprev < b) {
+            moveQueue.Enqueue(Tuple.Create(a + 1, b));
+          } else if (aprev == a && anext == a && bnext > b) {
+            moveQueue.Enqueue(Tuple.Create(a, b - 1));
+          } else if (aprev == a && anext == a && bnext == b && bprev == b) {
+            moveQueue.Enqueue(Tuple.Create(a, b - 1));
+          } else if (aprev == a && anext == a && bprev < b) {
+            moveQueue.Enqueue(Tuple.Create(a + 1, b));
+          } else if (anext > a && bnext > b) {
+            moveQueue.Enqueue(Tuple.Create(a, b - 1));
+          } else if (anext > a && bnext == b && bprev == b) {
+            moveQueue.Enqueue(Tuple.Create(a, b - 1));
+          } else /*if (anext > a && bprev < b)*/ {
+            moveQueue.Enqueue(Tuple.Create(a, bprev - 1));
+            moveQueue.Enqueue(Tuple.Create(bprev, b));
+          }
+
+          while (moveQueue.Count > 0) {
+            var m = moveQueue.Dequeue();
+            Opt(child, m.Item1, m.Item2);
+            undoStack.Push(m);
+          }
+          var moveF = eval(child);
+
+          evaluations++;
+          if (double.IsNaN(bestChange) || moveF < bestChange) {
+            bestChange = moveF;
+            bestQueue = new Queue<Tuple<int, int>>(undoStack.Reverse());
+          }
+          // undo
+          while (undoStack.Count > 0) {
+            var m = undoStack.Pop();
+            Opt(child, m.Item1, m.Item2);
+          }
+        }
+        if (!double.IsNaN(bestChange)) {
+          while (bestQueue.Count > 0) {
+            var m = bestQueue.Dequeue();
+            Opt(child, m.Item1, m.Item2);
+            for (var i = m.Item1; i <= m.Item2; i++) invChild[child[i]] = i;
+          }
+          yield return (Permutation) child.Clone();
+        }
+      } while (!double.IsNaN(bestChange));
+    }
+
+    private static bool IsUndirectedEdge(int[] invP, int a, int b) {
+      var d = Math.Abs(invP[a] - invP[b]);
+      return d == 1 || d == invP.Length - 1;
+    }
+
+    private static void Opt(Permutation child, int from, int to) {
+      if (from > to) child.Reverse(to, from - to + 1);
+      else child.Reverse(from, to - from + 1);
+    }
+  }
+}
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveInversionImprover.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveInversionImprover.cs	(revision 14776)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/LocalSearch/ExhaustiveInversionImprover.cs	(revision 14776)
@@ -0,0 +1,74 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using HeuristicLab.Algorithms.MemPR.Permutation.LocalSearch;
+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.Algorithms.MemPR.Permutation {
+  [Item("Exhaustive Inversion Improver", "")]
+  [StorableClass]
+  public class ExhaustiveInversionImprover : SingleSuccessorOperator, IImprovementOperator {
+    #region Parameter properties
+    public ILookupParameter<DoubleMatrix> DistanceMatrixParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public ILookupParameter<Encodings.PermutationEncoding.Permutation> PermutationParameter {
+      get { return (ILookupParameter<Encodings.PermutationEncoding.Permutation>)Parameters["Permutation"]; }
+    }
+    public ILookupParameter<IntValue> LocalEvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["LocalEvaluatedSolutions"]; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private ExhaustiveInversionImprover(bool deserializing) : base(deserializing) { }
+    private ExhaustiveInversionImprover(ExhaustiveInversionImprover original, Cloner cloner) : base(original, cloner) { }
+    public ExhaustiveInversionImprover()
+      : base() {
+      #region Create parameters
+      Parameters.Add(new LookupParameter<DoubleMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "A pseudo random number generator."));
+      Parameters.Add(new ValueLookupParameter<Encodings.PermutationEncoding.Permutation>("Permutation", "The solution to be improved. This parameter is used for name translation only."));
+      Parameters.Add(new LookupParameter<IntValue>("LocalEvaluatedSolutions", "The amount of locally evaluated solutions."));
+      #endregion
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExhaustiveInversionImprover(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var perm = PermutationParameter.ActualValue;
+
+      var distances = DistanceMatrixParameter.ActualValue;
+      Func<Encodings.PermutationEncoding.Permutation, CancellationToken, double> eval = (p, _) => {
+        double length = 0;
+        for (int i = 0; i < p.Length - 1; i++)
+          length += distances[p[i], p[i + 1]];
+        length += distances[p[p.Length - 1], p[0]];
+        return length;
+      };
+      var quality = eval(perm, CancellationToken.None);
+      var path = Exhaustive2Opt.HillClimb(random, perm, quality, false, eval, CancellationToken.None);
+      var final = path.Last();
+
+      LocalEvaluatedSolutionsParameter.ActualValue = new IntValue(final.Item3);
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/StaticAPI/Trainer.cs
===================================================================
--- branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/StaticAPI/Trainer.cs	(revision 14695)
+++ branches/PerformanceComparison/HeuristicLab.Algorithms.MemPR/3.3/Permutation/SolutionModel/Univariate/StaticAPI/Trainer.cs	(revision 14776)
@@ -22,7 +22,7 @@
 using System;
 using System.Collections.Generic;
-using HeuristicLab.Algorithms.MemPR.Interfaces;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
 
 namespace HeuristicLab.Algorithms.MemPR.Permutation.SolutionModel.Univariate {
