Index: branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/Cluster.cs
===================================================================
--- branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/Cluster.cs	(revision 14424)
+++ branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/Cluster.cs	(revision 14424)
@@ -0,0 +1,146 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading.Tasks;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+
+
+  public class ClusterAlgorithm<C,CO> where C : Cluster<CO> where CO : ClusterElement {
+
+    //public static List<C> KMeans(IVRPProblemInstance instance, IRandom random, List<CO> clusterObjects, int k, double changeThreshold) {
+    //  HashSet<int> initMeans = new HashSet<int>();
+    //  int nextMean = -1;
+
+    //  for (int i = 0; i < k && i < clusterObjects.Count; i++) {
+    //    //C cluster = new C()
+    //  }
+
+
+
+
+    //}
+
+    //private static int KMeansRun(List<C> clusters, List<CO> clusterObjects) {
+      
+    //}
+
+  }
+
+  #region Cluster
+  public interface ICluster<T> where T : IClusterElement {
+    double CalculateImpact(T o);
+    void CalculateMean();
+    void SetMean(T o);
+    bool AddObject(T o);
+  }
+  public abstract class Cluster<T> : ICluster<T> where T : ClusterElement {
+    public int Id;
+    protected readonly IVRPProblemInstance instance;
+    public List<T> Objects { get; private set; }
+
+    public T Mean { get; set; }
+
+    public Cluster(IVRPProblemInstance instance, int id) {
+      this.instance = instance;
+      Id = id;
+      Objects = new List<T>();
+
+    }
+    public bool AddObject(T o) {
+      Objects.Add(o);
+
+      bool clusterChanged = o.ClusterId != Id;
+      o.ClusterId = Id;
+      return clusterChanged;
+    }
+
+    public void SetMean(T o) {
+      Mean = o;
+      Mean.ClusterId = Id;
+    }
+
+    public abstract void CalculateMean();
+
+    public abstract double CalculateImpact(T o);
+
+  }
+  public class SpatialDistanceCluster : Cluster<SpatialDistanceClusterElement> {
+    public SpatialDistanceCluster(IVRPProblemInstance instance, int id) : base(instance, id) {
+    }
+
+    public override void CalculateMean() {
+      int dimensions = instance.Coordinates.Columns;
+      SpatialDistanceClusterElement mean = new SpatialDistanceClusterElement(-1, Id, dimensions);
+      foreach (SpatialDistanceClusterElement o in Objects) {
+        double[] coordinates = instance.GetCoordinates(o.Id);
+        for (int i = 0; i < coordinates.Length; i++) {
+          mean.Coordinates[i] += (coordinates[i] / Objects.Count);
+        }
+      }
+      Mean = mean;
+    }
+
+    public override double CalculateImpact(SpatialDistanceClusterElement o) {
+      if (Mean == null)
+        CalculateMean();
+
+      return Math.Pow(Mean.GetDistance(o), 2) / ((Objects.Count > 0) ? Objects.Count : 1);
+    }
+  }
+  #endregion Cluster
+
+
+  #region ClusterElement
+  public interface IClusterElement {
+    double GetDistance(IClusterElement o);
+  }
+  public abstract class ClusterElement : IClusterElement {
+    public int Id { get; set; }
+    public int ClusterId { get; set; }
+
+    private ClusterElement() { }
+
+    public ClusterElement(int id, int clusterId = -1) {
+      Id = id;
+      ClusterId = clusterId;
+    }
+
+    public abstract double GetDistance(IClusterElement o);
+  }
+  public class SpatialDistanceClusterElement : ClusterElement {
+
+    public double[] Coordinates { get; set; }
+
+    public SpatialDistanceClusterElement(int id, int clusterId = -1) : base(id, clusterId) {
+    }
+
+    public SpatialDistanceClusterElement(int id, double[] coordinates, int clusterId = -1) : base(id, clusterId) {
+      Coordinates = coordinates;
+    }
+
+    public SpatialDistanceClusterElement(int id, int dimensions, int clusterId = -1) : base(id, clusterId) { 
+      Coordinates = new double[dimensions];
+    }
+
+    public override double GetDistance(IClusterElement o) {
+      var other = o as SpatialDistanceClusterElement;
+      if (other == null) {
+        throw new ArrayTypeMismatchException(string.Format("Distance calculation between {0} and {1} is not possible.",
+          typeof(SpatialDistanceClusterElement), o.GetType()));
+      }
+
+      double distance = 0.0;
+      for (int i = 0; i < other.Coordinates.Length; i++) {
+        distance += Math.Pow(Coordinates[i] - other.Coordinates[i], 2);
+      }
+
+      return Math.Sqrt(distance);
+    }
+  }
+  #endregion ClusterElement
+}
Index: branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/ClusterCreator.cs
===================================================================
--- branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/ClusterCreator.cs	(revision 14417)
+++ branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/ClusterCreator.cs	(revision 14424)
@@ -37,5 +37,5 @@
   [Item("ClusterCreator", "Creates a VRP solution by clustering customers first with a KMeans-algorithm and building tours afterwards alternatevly in a random or a greedy fashion.")]
   [StorableClass]
-  public sealed class ClusterCreator : PotvinCreator, IStochasticOperator {
+  public abstract class ClusterCreator : PotvinCreator, IStochasticOperator {
 
     public ILookupParameter<IRandom> RandomParameter {
@@ -69,254 +69,9 @@
     }
 
-    private ClusterCreator(ClusterCreator original, Cloner cloner)
+    protected ClusterCreator(ClusterCreator original, Cloner cloner)
       : base(original, cloner) {
     }
 
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new ClusterCreator(this, cloner);
-    }
-
-    public static PotvinEncoding CreateSolution(IVRPProblemInstance instance, IRandom random, int minK, int maxK, double clusterChangeThreshold, int creationOption) {
-      PotvinEncoding result = new PotvinEncoding(instance);
-
-      IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
-
-      // add all customers
-      List<int> customers = new List<int>();
-      for (int i = 1; i <= instance.Cities.Value; i++) {
-        if(pdp == null || pdp.GetDemand(i) >= 0)
-          customers.Add(i);
-      }
-
-      // cluster by spatial distribution
-
-      // (1) wrap stops in ClusterObject
-      List<ClusterObject> clusterObjects = new List<ClusterObject>();
-      foreach (int customer in customers) {
-        clusterObjects.Add(new ClusterObject(customer, instance.GetCoordinates(customer)));
-      }
-
-      // (2) cluster
-      int k = random.Next(minK, maxK);
-      List<Cluster> clusters = KMeans(instance, random, clusterObjects, k, clusterChangeThreshold);
-
-      // (3) build tours
-      // (a) shuffle
-      // (b) greedy
-      foreach (Cluster c in clusters) {
-        Tour newTour = new Tour();
-        result.Tours.Add(newTour);
-
-        if (creationOption == 0) {
-          // (a) shuffle
-          c.Objects.Shuffle(random);
-          foreach (ClusterObject o in c.Objects) {
-            newTour.Stops.Add(o.Id);
-          }
-        } else {
-          // (b) greedy
-          foreach (ClusterObject o in c.Objects) {
-            newTour.Stops.Add(o.Id);
-          }
-          GreedyTourCreation(instance, result, newTour, false);
-        }
-      }
-      return result;
-    }
-
-    public override IOperation InstrumentedApply() {
-      IRandom random = RandomParameter.ActualValue;
-
-      int minK = (MinK.Value.Value > 0) ? MinK.Value.Value : 1;
-      int maxK = (MaxK.Value != null) ? MaxK.Value.Value : ProblemInstance.Vehicles.Value;
-      double clusterChangeThreshold = (ClusterChangeThreshold.Value.Value >= 0.0 &&
-                                       ClusterChangeThreshold.Value.Value <= 1.0)
-        ? ClusterChangeThreshold.Value.Value
-        : 0.0;
-
-      // normalize probabilities
-      double max = TourCreationProbabilities.Value.Max();
-      double[] probabilites = new double[2];
-      for (int i = 0; i < TourCreationProbabilities.Value.Length; i++) {
-        probabilites[i] = TourCreationProbabilities.Value[i] / max;
-      }
-
-      List<int> creationOptions = new List<int>() {0, 1};
-      int creationOption = creationOptions.SampleProportional(random, 1, probabilites, false, false).First();
-
-      VRPToursParameter.ActualValue = CreateSolution(ProblemInstance, random, minK, maxK, clusterChangeThreshold, creationOption);
-      return base.InstrumentedApply();
-    }
-
-    private static List<Cluster> KMeans(IVRPProblemInstance instance, IRandom random, List<ClusterObject> objects, int k, double changeTreshold) {
-
-      List<Cluster> clusters = new List<Cluster>();
-      HashSet<int> initMeans = new HashSet<int>();
-      int nextMean = -1;
-
-      // (1) initialize each cluster with a random first object (i.e. mean)
-      for (int i = 0; i < k && i < objects.Count; i++) {
-        Cluster cluster = new Cluster(instance, i);
-
-        do {
-          nextMean = random.Next(0, objects.Count);
-        } while (initMeans.Contains(nextMean));
-        initMeans.Add(nextMean);
-        cluster.SetMean(objects[nextMean]);
-        clusters.Add(cluster);
-      }
-
-      // (2) repeat clustering until change rate is below threshold
-      int changes = 0;
-      double changeRate = 1.0;
-
-      do {
-        changes = KMeansRun(clusters, objects);
-        changeRate = changes / objects.Count;
-
-      } while (changeRate > changeTreshold);
-
-      // remove empty clusters
-      clusters.RemoveAll(c => c.Objects.Count.Equals(0));
-
-      return clusters;
-    }
-
-    private static int KMeansRun(List<Cluster> clusters, List<ClusterObject> objects) {
-      int changes = 0;
-
-      foreach (Cluster c in clusters) {
-        c.Objects.Clear();
-      }
-
-      foreach (ClusterObject o in objects) {
-        int bestClusterIdx = -1;
-        double minImpact = double.MaxValue;
-        for(int i = 0; i < clusters.Count; i++) {
-          double impact = clusters[i].CalculateVarianceIncrease(o);
-          if (impact < minImpact) {
-            minImpact = impact;
-            bestClusterIdx = i;
-          }
-        }
-        clusters[bestClusterIdx].AddObject(o);
-      }
-
-      foreach (Cluster c in clusters) {
-        c.CalculateMean();
-      }
-
-      return changes;
-    }
-
-    class Cluster {
-      public int Id;
-      public List<ClusterObject> Objects { get; private set; }
-      public double Variance { get; private set; }
-      public ClusterObject Mean { get; set; }
-
-      private readonly IVRPProblemInstance instance;
-
-      public Cluster(IVRPProblemInstance instance, int id) {
-        this.instance = instance;
-        Id = id;
-        Objects = new List<ClusterObject>();
-      }
-
-      public bool IsEqual(Cluster cluster) {
-        bool equal = (cluster != null) && (cluster.Objects.Count == Objects.Count);
-        int index = 0;
-
-        while (equal && index < Objects.Count) {
-          equal = cluster.Objects.Contains(Objects[index]);
-          index++;
-        }
-        return equal;
-      }
-
-      public bool AddObject(ClusterObject o) {
-        Objects.Add(o);
-
-        bool clusterChanged = o.ClusterId != Id;
-        o.ClusterId = Id;
-        return clusterChanged;
-      }
-
-      public void SetMean(ClusterObject o) {
-        Mean = o;
-        Mean.ClusterId = Id;
-      }
-
-      public ClusterObject CalculateMean() {
-        int dimensions = instance.Coordinates.Columns;
-        ClusterObject mean = new ClusterObject(-1, Id, dimensions);
-        foreach (ClusterObject o in Objects) {
-          double[] coordinates = instance.GetCoordinates(o.Id);
-          for (int i = 0; i < coordinates.Length; i++) {
-            mean.Coordinates[i] += (coordinates[i] / Objects.Count);
-          }
-        }
-        Mean = mean;
-        return Mean;
-      }
-
-      public double CalculateVariance() {
-        Variance = 0.0;
-
-        if (Mean == null)
-          CalculateMean();
-
-        foreach (ClusterObject o in Objects) {
-          double[] coordinates = instance.GetCoordinates(o.Id);
-          Variance += Math.Pow(Mean.GetDistance(o.Coordinates), 2);
-        }
-        return Variance /= Objects.Count;
-      }
-
-      public double CalculateVarianceIncrease(ClusterObject o) {
-        if(Mean == null)
-          CalculateMean();
-
-        return Math.Pow(Mean.GetDistance(o.Coordinates), 2) / ((Objects.Count > 0) ? Objects.Count : 1);
-      }
-    }
-
-    class ClusterObject {
-      
-      public int Id { get; private set; }
-
-      public int ClusterId { get; set; }
-
-      public double[] Coordinates { get; set; }
-
-      public ClusterObject() { }
-
-      public ClusterObject(int id, int clusterId = -1) {
-        Id = id;
-        ClusterId = clusterId;
-      }
-
-      public ClusterObject(int id, double[] coordinates) {
-        Id = id;
-        Coordinates = coordinates;
-      }
-
-      public ClusterObject(int id, int clusterId, int dimensions) {
-        Id = id;
-        ClusterId = clusterId;
-        Coordinates = new double[dimensions];
-      }
-
-      public double GetDistance(double[] otherCoordinates) {
-        double distance = 0.0;
-
-        for (int i = 0; i < otherCoordinates.Length; i++) {
-          distance += Math.Pow(Coordinates[i] - otherCoordinates[i], 2);
-        }
-        return Math.Sqrt(distance);
-      }
-    }
-
-    private static double CalculateAngleToDepot(IVRPProblemInstance instance, int city) {
+    protected static double CalculateAngleToDepot(IVRPProblemInstance instance, int city) {
       double dx = instance.GetCoordinates(0)[0];
       double dy = instance.GetCoordinates(0)[1];
@@ -336,5 +91,5 @@
     }
 
-    private static void GreedyTourCreation(IVRPProblemInstance instance, PotvinEncoding individual, Tour tour, bool includeCosts) {
+    protected static void GreedyTourCreation(IVRPProblemInstance instance, PotvinEncoding individual, Tour tour, bool includeCosts) {
       Tour unrouted = tour.Clone() as Tour;
       tour.Stops.Clear();
Index: branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/GeographicDistanceClusterCreator.cs
===================================================================
--- branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/GeographicDistanceClusterCreator.cs	(revision 14424)
+++ branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/GeographicDistanceClusterCreator.cs	(revision 14424)
@@ -0,0 +1,187 @@
+﻿#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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.VehicleRouting.Interfaces;
+using HeuristicLab.Problems.VehicleRouting.Variants;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
+  [Item("GeographicDistanceClusterCreator", "Creates a VRP solution by clustering customers first with a KMeans-algorithm based on their geographic position and building tours afterwards alternatevly in a random or a greedy fashion.")]
+  [StorableClass]
+  public sealed class GeographicDistanceClusterCreator : ClusterCreator {
+
+    [StorableConstructor]
+    private GeographicDistanceClusterCreator(bool deserializing) : base(deserializing) { }
+
+    public GeographicDistanceClusterCreator() : base() {
+    }
+
+    private GeographicDistanceClusterCreator(GeographicDistanceClusterCreator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GeographicDistanceClusterCreator(this, cloner);
+    }
+
+    public static List<SpatialDistanceClusterElement> CreateClusterObjects(IVRPProblemInstance instance) {
+      IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance;
+
+      // add all customers
+      List<int> customers = new List<int>();
+      for (int i = 1; i <= instance.Cities.Value; i++) {
+        if (pdp == null || pdp.GetDemand(i) >= 0)
+          customers.Add(i);
+      }
+
+      // wrap stops in SpatialDistanceClusterElement
+      List<SpatialDistanceClusterElement> clusterObjects = new List<SpatialDistanceClusterElement>();
+      foreach (int customer in customers) {
+        clusterObjects.Add(new SpatialDistanceClusterElement(customer, instance.GetCoordinates(customer)));
+      }
+      return clusterObjects;
+    }
+
+    public static PotvinEncoding CreateSolution(IVRPProblemInstance instance, IRandom random, int minK, int maxK, double clusterChangeThreshold, int creationOption) {
+      PotvinEncoding result = new PotvinEncoding(instance);
+
+      List<SpatialDistanceClusterElement> clusterObjects = CreateClusterObjects(instance);
+
+      int k = random.Next(minK, maxK);
+      List<SpatialDistanceCluster> clusters = KMeans(instance, random, clusterObjects, k, clusterChangeThreshold);
+
+      // (3) build tours
+      // (a) shuffle
+      // (b) greedy
+      foreach (var c in clusters) {
+        Tour newTour = new Tour();
+        result.Tours.Add(newTour);
+
+        if (creationOption == 0) {
+          // (a) shuffle
+          c.Objects.Shuffle(random);
+          foreach (var o in c.Objects) {
+            newTour.Stops.Add(o.Id);
+          }
+        } else {
+          // (b) greedy
+          foreach (var o in c.Objects) {
+            newTour.Stops.Add(o.Id);
+          }
+          GreedyTourCreation(instance, result, newTour, false);
+        }
+      }
+
+      return result;
+    }
+
+    private static List<SpatialDistanceCluster> KMeans(IVRPProblemInstance instance, IRandom random, List<SpatialDistanceClusterElement> objects, int k, double changeTreshold) {
+
+      List<SpatialDistanceCluster> clusters = new List<SpatialDistanceCluster>();
+      HashSet<int> initMeans = new HashSet<int>();
+      int nextMean = -1;
+
+      // (1) initialize each cluster with a random first object (i.e. mean)
+      for (int i = 0; i < k && i < objects.Count; i++) {
+        SpatialDistanceCluster cluster = new SpatialDistanceCluster(instance, i);
+
+        do {
+          nextMean = random.Next(0, objects.Count);
+        } while (initMeans.Contains(nextMean));
+        initMeans.Add(nextMean);
+        cluster.SetMean(objects[nextMean]);
+        clusters.Add(cluster);
+      }
+
+      // (2) repeat clustering until change rate is below threshold
+      int changes = 0;
+      double changeRate = 1.0;
+
+      do {
+        changes = KMeansRun(clusters, objects);
+        changeRate = changes / objects.Count;
+
+      } while (changeRate > changeTreshold);
+
+      // remove empty clusters
+      clusters.RemoveAll(c => c.Objects.Count.Equals(0));
+
+      return clusters;
+    }
+
+    private static int KMeansRun(List<SpatialDistanceCluster> clusters, List<SpatialDistanceClusterElement> objects) {
+      int changes = 0;
+
+      foreach (var c in clusters) {
+        c.Objects.Clear();
+      }
+
+      foreach (var o in objects) {
+        int bestClusterIdx = -1;
+        double minImpact = double.MaxValue;
+        for (int i = 0; i < clusters.Count; i++) {
+          double impact = clusters[i].CalculateImpact(o);
+          if (impact < minImpact) {
+            minImpact = impact;
+            bestClusterIdx = i;
+          }
+        }
+        if (clusters[bestClusterIdx].AddObject(o))
+          changes++;
+      }
+
+      foreach (var c in clusters) {
+        c.CalculateMean();
+      }
+
+      return changes;
+    }
+
+    public override IOperation InstrumentedApply() {
+      IRandom random = RandomParameter.ActualValue;
+
+      int minK = (MinK.Value.Value > 0) ? MinK.Value.Value : 1;
+      int maxK = (MaxK.Value != null) ? MaxK.Value.Value : ProblemInstance.Vehicles.Value;
+      double clusterChangeThreshold = (ClusterChangeThreshold.Value.Value >= 0.0 &&
+                                       ClusterChangeThreshold.Value.Value <= 1.0)
+        ? ClusterChangeThreshold.Value.Value
+        : 0.0;
+
+      // normalize probabilities
+      double max = TourCreationProbabilities.Value.Max();
+      double[] probabilites = new double[2];
+      for (int i = 0; i < TourCreationProbabilities.Value.Length; i++) {
+        probabilites[i] = TourCreationProbabilities.Value[i] / max;
+      }
+
+      List<int> creationOptions = new List<int>() { 0, 1 };
+      int creationOption = creationOptions.SampleProportional(random, 1, probabilites, false, false).First();
+
+      VRPToursParameter.ActualValue = CreateSolution(ProblemInstance, random, minK, maxK, clusterChangeThreshold, creationOption);
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj
===================================================================
--- branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 14417)
+++ branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 14424)
@@ -48,4 +48,5 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>5</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -195,5 +196,7 @@
     <Compile Include="Analyzer\ConstraintRelaxation\TimeWindowed\TimeWindowRelaxationVRPAnalyzer.cs" />
     <Compile Include="Analyzer\VRPSolution.cs" />
+    <Compile Include="Encodings\Potvin\Creators\Cluster.cs" />
     <Compile Include="Encodings\Potvin\Creators\ClusterCreator.cs" />
+    <Compile Include="Encodings\Potvin\Creators\GeographicDistanceClusterCreator.cs" />
     <Compile Include="Encodings\Potvin\Crossovers\PotvinEdgePreservingSequenceBasedCrossover.cs" />
     <Compile Include="Encodings\Potvin\Manipulators\PotvinGreedyTourCreationManipulator.cs" />
