Index: branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/HeuristicLab.Problems.Instances.TSPLIB-3.3.csproj
===================================================================
--- branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/HeuristicLab.Problems.Instances.TSPLIB-3.3.csproj	(revision 13412)
+++ branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/HeuristicLab.Problems.Instances.TSPLIB-3.3.csproj	(revision 13470)
@@ -123,8 +123,8 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="MarsagliaRandom.cs" />
     <Compile Include="TSPLIBHeterogeneousPTSPDataDescriptor.cs" />
     <Compile Include="TSPLIBHomogeneousPTSPDataDescriptor.cs" />
     <Compile Include="TSPLIBHeterogeneousPTSPInstanceProvider.cs" />
+    <Compile Include="TSPLIBPTSPInstanceProvider.cs" />
     <Compile Include="TSPLIBInstanceProvider.cs" />
     <Compile Include="TSPLIBATSPInstanceProvider.cs" />
Index: branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/MarsagliaRandom.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/MarsagliaRandom.cs	(revision 13412)
+++ 	(revision )
@@ -1,56 +1,0 @@
-﻿
-namespace HeuristicLab.Problems.Instances.TSPLIB {
-  /// <summary>
-  /// This class is used to randomly generate PTSP instances given the TSPLIB instances.
-  /// An own implementation of a RNG was used in order to avoid possible implementation changes
-  /// in future .NET versions which would result in entirely different instances.
-  /// </summary>
-  internal class MarsagliaRandom {
-    /*
-     * S = 2111111111*X[n-4] + 1492*X[n-3] + 1776*X[n-2] + 5115*X[n-1] + C
-     * X[n] = S modulo 2^32
-     * C = floor(S / 2^32)
-     * 
-     */
-    private readonly uint[] mem = new uint[4];
-    private uint c;
-
-    public MarsagliaRandom(uint s) {
-      Seed(s);
-    }
-
-    private uint Next() {
-      unchecked {
-        ulong wsum = 2111111111 * mem[0]
-                    + 1492 * mem[1]
-                    + 1776 * mem[2]
-                    + 5115 * mem[3]
-                    + c;
-
-        mem[0] = mem[1];
-        mem[1] = mem[2];
-        mem[2] = mem[3];
-        mem[3] = (uint)wsum;
-        c = (uint)(wsum >> 32);
-        return mem[3];
-      }
-    }
-
-    public double NextDouble() {
-      return (double)Next() / uint.MaxValue;
-    }
-
-    public void Seed(uint seed) {
-      int i;
-      for (i = 0; i < mem.Length; i++) {
-        unchecked {
-          seed = seed * 31294061 + 1;
-        }
-        mem[i] = seed;
-      }
-      unchecked {
-        c = seed * 31294061 + 1;
-      }
-    }
-  }
-}
Index: branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPInstanceProvider.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPInstanceProvider.cs	(revision 13412)
+++ branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPInstanceProvider.cs	(revision 13470)
@@ -22,9 +22,8 @@
 using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Linq;
 
 namespace HeuristicLab.Problems.Instances.TSPLIB {
-  public class TSPLIBHeterogeneousPTSPInstanceProvider : TSPLIBInstanceProvider<PTSPData> {
+  public class TSPLIBHeterogeneousPTSPInstanceProvider : TSPLIBPTSPInstanceProvider {
 
     public override string Name {
@@ -32,13 +31,6 @@
     }
 
-    public override string Description {
-      get { return "Traveling Salesman Problem Library"; }
-    }
-
-    protected override string FileExtension { get { return "tsp"; } }
-
     public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
       foreach (var desc in base.GetDataDescriptors().OfType<TSPLIBDataDescriptor>()) {
-        desc.Name += " [0.1;0.9]";
         desc.SolutionIdentifier = null;
         yield return desc;
@@ -46,63 +38,66 @@
     }
 
-    protected override PTSPData LoadInstance(TSPLIBParser parser, IDataDescriptor descriptor = null) {
-      parser.Parse();
-      if (parser.FixedEdges != null) throw new InvalidDataException("TSP instance " + parser.Name + " contains fixed edges which are not supported by HeuristicLab.");
-      var instance = new PTSPData();
-      instance.Dimension = parser.Dimension;
-      instance.Coordinates = parser.Vertices != null ? parser.Vertices : parser.DisplayVertices;
-      instance.Distances = parser.Distances;
-      switch (parser.EdgeWeightType) {
-        case TSPLIBEdgeWeightTypes.ATT:
-          instance.DistanceMeasure = DistanceMeasure.Att; break;
-        case TSPLIBEdgeWeightTypes.CEIL_2D:
-          instance.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
-        case TSPLIBEdgeWeightTypes.EUC_2D:
-          instance.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
-        case TSPLIBEdgeWeightTypes.EUC_3D:
-          throw new InvalidDataException("3D coordinates are not supported.");
-        case TSPLIBEdgeWeightTypes.EXPLICIT:
-          instance.DistanceMeasure = DistanceMeasure.Direct; break;
-        case TSPLIBEdgeWeightTypes.GEO:
-          instance.DistanceMeasure = DistanceMeasure.Geo; break;
-        case TSPLIBEdgeWeightTypes.MAN_2D:
-          instance.DistanceMeasure = DistanceMeasure.Manhattan; break;
-        case TSPLIBEdgeWeightTypes.MAN_3D:
-          throw new InvalidDataException("3D coordinates are not supported.");
-        case TSPLIBEdgeWeightTypes.MAX_2D:
-          instance.DistanceMeasure = DistanceMeasure.Maximum; break;
-        case TSPLIBEdgeWeightTypes.MAX_3D:
-          throw new InvalidDataException("3D coordinates are not supported.");
-        default:
-          throw new InvalidDataException("The given edge weight is not supported by HeuristicLab.");
+    protected override double[] GetProbabilities(IDataDescriptor descriptor, PTSPData instance) {
+      var random = new MarsagliaRandom(GetInstanceHash(instance.Name));
+      return Enumerable.Range(0, instance.Dimension).Select(_ => (int)Math.Round((0.1 + 0.9 * random.NextDouble()) * 100) / 100.0).ToArray();
+    }
+
+    // Bernstein's hash function
+    private uint GetInstanceHash(string name) {
+      uint hash = 5381;
+      var len = name.Length;
+      for (var i = 0; i < len; i++)
+        unchecked { hash = ((hash * 33) + name[i]); }
+      return hash;
+    }
+
+    /// <summary>
+    /// This class is used to randomly generate PTSP instances given the TSPLIB instances.
+    /// An own implementation of a RNG was used in order to avoid possible implementation changes
+    /// in future .NET versions which would result in entirely different instances.
+    /// </summary>
+    /// <remarks>
+    /// RNG is implemented according to George Marsaglia https://en.wikipedia.org/wiki/Multiply-with-carry
+    /// </remarks>
+    private class MarsagliaRandom {
+      /*
+       * S = 2111111111*X[n-4] + 1492*X[n-3] + 1776*X[n-2] + 5115*X[n-1] + C
+       * X[n] = S modulo 2^32
+       * C = floor(S / 2^32)
+       * 
+       */
+      private readonly uint[] mem = new uint[4];
+      private uint c;
+
+      public MarsagliaRandom(uint s) {
+        int i;
+        for (i = 0; i < mem.Length; i++) {
+          unchecked { s = s * 31294061 + 1; }
+          mem[i] = s;
+        }
+        unchecked { c = s * 31294061 + 1; }
       }
 
-      instance.Name = parser.Name;
-      instance.Description = parser.Comment
-        + Environment.NewLine + Environment.NewLine
-        + GetInstanceDescription();
+      private uint Next() {
+        unchecked {
+          ulong wsum = 2111111111 * mem[0]
+                      + 1492 * mem[1]
+                      + 1776 * mem[2]
+                      + 5115 * mem[3]
+                      + c;
 
-      var random = new MarsagliaRandom((uint)(descriptor != null ? descriptor.Name : instance.Name).GetHashCode());
-      instance.Probabilities = Enumerable.Range(0, instance.Dimension).Select(_ => 0.1 + 0.9 * random.NextDouble()).ToArray();
+          mem[0] = mem[1];
+          mem[1] = mem[2];
+          mem[2] = mem[3];
+          mem[3] = (uint)wsum;
+          c = (uint)(wsum >> 32);
+          return mem[3];
+        }
+      }
 
-      return instance;
+      public double NextDouble() {
+        return (double)Next() / uint.MaxValue;
+      }
     }
-
-    protected override void LoadSolution(TSPLIBParser parser, PTSPData instance) {
-      parser.Parse();
-      instance.BestKnownTour = parser.Tour.FirstOrDefault();
-    }
-
-    public PTSPData LoadData(string tspFile, string tourFile, double? bestQuality) {
-      var data = LoadInstance(new TSPLIBParser(tspFile));
-      if (!String.IsNullOrEmpty(tourFile)) {
-        var tourParser = new TSPLIBParser(tourFile);
-        LoadSolution(tourParser, data);
-      }
-      if (bestQuality.HasValue)
-        data.BestKnownQuality = bestQuality.Value;
-      return data;
-    }
-
   }
 }
Index: branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPInstanceProvider.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPInstanceProvider.cs	(revision 13412)
+++ branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPInstanceProvider.cs	(revision 13470)
@@ -20,13 +20,11 @@
 #endregion
 
-using System;
 using System.Collections.Generic;
 using System.Globalization;
-using System.IO;
 using System.Linq;
 
 namespace HeuristicLab.Problems.Instances.TSPLIB {
-  public class TSPLIBHomogeneousPTSPInstanceProvider : TSPLIBInstanceProvider<PTSPData> {
-    private static readonly double[] probabilities = new[] { 0.1, 0.2, 0.4, 0.5, 0.6, 0.8, 0.9, 1.0 };
+  public class TSPLIBHomogeneousPTSPInstanceProvider : TSPLIBPTSPInstanceProvider {
+    private static readonly double[] Probabilities = new[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
 
     public override string Name {
@@ -34,14 +32,8 @@
     }
 
-    public override string Description {
-      get { return "Traveling Salesman Problem Library"; }
-    }
-
-    protected override string FileExtension { get { return "tsp"; } }
-
     public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
       var tspDescriptors = base.GetDataDescriptors().OfType<TSPLIBDataDescriptor>();
       foreach (var desc in tspDescriptors) {
-        foreach (var p in probabilities) {
+        foreach (var p in Probabilities) {
           yield return new TSPLIBHomogeneousPTSPDataDescriptor(
             desc.Name + "-" + p.ToString(CultureInfo.InvariantCulture.NumberFormat),
@@ -54,63 +46,9 @@
     }
 
-    protected override PTSPData LoadInstance(TSPLIBParser parser, IDataDescriptor descriptor = null) {
-      parser.Parse();
-      if (parser.FixedEdges != null) throw new InvalidDataException("TSP instance " + parser.Name + " contains fixed edges which are not supported by HeuristicLab.");
-      var instance = new PTSPData();
-      instance.Dimension = parser.Dimension;
-      instance.Coordinates = parser.Vertices != null ? parser.Vertices : parser.DisplayVertices;
-      instance.Distances = parser.Distances;
-      switch (parser.EdgeWeightType) {
-        case TSPLIBEdgeWeightTypes.ATT:
-          instance.DistanceMeasure = DistanceMeasure.Att; break;
-        case TSPLIBEdgeWeightTypes.CEIL_2D:
-          instance.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
-        case TSPLIBEdgeWeightTypes.EUC_2D:
-          instance.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
-        case TSPLIBEdgeWeightTypes.EUC_3D:
-          throw new InvalidDataException("3D coordinates are not supported.");
-        case TSPLIBEdgeWeightTypes.EXPLICIT:
-          instance.DistanceMeasure = DistanceMeasure.Direct; break;
-        case TSPLIBEdgeWeightTypes.GEO:
-          instance.DistanceMeasure = DistanceMeasure.Geo; break;
-        case TSPLIBEdgeWeightTypes.MAN_2D:
-          instance.DistanceMeasure = DistanceMeasure.Manhattan; break;
-        case TSPLIBEdgeWeightTypes.MAN_3D:
-          throw new InvalidDataException("3D coordinates are not supported.");
-        case TSPLIBEdgeWeightTypes.MAX_2D:
-          instance.DistanceMeasure = DistanceMeasure.Maximum; break;
-        case TSPLIBEdgeWeightTypes.MAX_3D:
-          throw new InvalidDataException("3D coordinates are not supported.");
-        default:
-          throw new InvalidDataException("The given edge weight is not supported by HeuristicLab.");
-      }
-
-      instance.Name = parser.Name;
-      instance.Description = parser.Comment
-        + Environment.NewLine + Environment.NewLine
-        + GetInstanceDescription();
+    protected override double[] GetProbabilities(IDataDescriptor descriptor, PTSPData instance) {
       var ptspDesc = descriptor as TSPLIBHomogeneousPTSPDataDescriptor;
-      instance.Probabilities = ptspDesc != null ? Enumerable.Range(0, instance.Dimension).Select(_ => ptspDesc.Probability).ToArray()
-                                                : Enumerable.Range(0, instance.Dimension).Select(_ => 0.5).ToArray();
-
-      return instance;
+      return ptspDesc != null ? Enumerable.Range(0, instance.Dimension).Select(_ => ptspDesc.Probability).ToArray()
+                              : Enumerable.Range(0, instance.Dimension).Select(_ => 0.5).ToArray();
     }
-
-    protected override void LoadSolution(TSPLIBParser parser, PTSPData instance) {
-      parser.Parse();
-      instance.BestKnownTour = parser.Tour.FirstOrDefault();
-    }
-
-    public PTSPData LoadData(string tspFile, string tourFile, double? bestQuality) {
-      var data = LoadInstance(new TSPLIBParser(tspFile));
-      if (!String.IsNullOrEmpty(tourFile)) {
-        var tourParser = new TSPLIBParser(tourFile);
-        LoadSolution(tourParser, data);
-      }
-      if (bestQuality.HasValue)
-        data.BestKnownQuality = bestQuality.Value;
-      return data;
-    }
-
   }
 }
Index: branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBPTSPInstanceProvider.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBPTSPInstanceProvider.cs	(revision 13470)
+++ branches/PTSP/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBPTSPInstanceProvider.cs	(revision 13470)
@@ -0,0 +1,95 @@
+﻿#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 System.IO;
+using System.Linq;
+
+namespace HeuristicLab.Problems.Instances.TSPLIB {
+  public abstract class TSPLIBPTSPInstanceProvider : TSPLIBInstanceProvider<PTSPData> {
+
+    public override string Description {
+      get { return "Traveling Salesman Problem Library (adapted for generating PTSP instances)"; }
+    }
+
+    protected override string FileExtension { get { return "tsp"; } }
+
+    protected override PTSPData LoadInstance(TSPLIBParser parser, IDataDescriptor descriptor = null) {
+      parser.Parse();
+      if (parser.FixedEdges != null) throw new InvalidDataException("TSP instance " + parser.Name + " contains fixed edges which are not supported by HeuristicLab.");
+      var instance = new PTSPData();
+      instance.Dimension = parser.Dimension;
+      instance.Coordinates = parser.Vertices != null ? parser.Vertices : parser.DisplayVertices;
+      instance.Distances = parser.Distances;
+      switch (parser.EdgeWeightType) {
+        case TSPLIBEdgeWeightTypes.ATT:
+          instance.DistanceMeasure = DistanceMeasure.Att; break;
+        case TSPLIBEdgeWeightTypes.CEIL_2D:
+          instance.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
+        case TSPLIBEdgeWeightTypes.EUC_2D:
+          instance.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
+        case TSPLIBEdgeWeightTypes.EUC_3D:
+          throw new InvalidDataException("3D coordinates are not supported.");
+        case TSPLIBEdgeWeightTypes.EXPLICIT:
+          instance.DistanceMeasure = DistanceMeasure.Direct; break;
+        case TSPLIBEdgeWeightTypes.GEO:
+          instance.DistanceMeasure = DistanceMeasure.Geo; break;
+        case TSPLIBEdgeWeightTypes.MAN_2D:
+          instance.DistanceMeasure = DistanceMeasure.Manhattan; break;
+        case TSPLIBEdgeWeightTypes.MAN_3D:
+          throw new InvalidDataException("3D coordinates are not supported.");
+        case TSPLIBEdgeWeightTypes.MAX_2D:
+          instance.DistanceMeasure = DistanceMeasure.Maximum; break;
+        case TSPLIBEdgeWeightTypes.MAX_3D:
+          throw new InvalidDataException("3D coordinates are not supported.");
+        default:
+          throw new InvalidDataException("The given edge weight is not supported by HeuristicLab.");
+      }
+
+      instance.Name = parser.Name;
+      instance.Description = parser.Comment
+        + Environment.NewLine + Environment.NewLine
+        + GetInstanceDescription();
+
+      instance.Probabilities = GetProbabilities(descriptor, instance);
+      return instance;
+    }
+
+    protected abstract double[] GetProbabilities(IDataDescriptor descriptor, PTSPData instance);
+
+    protected override void LoadSolution(TSPLIBParser parser, PTSPData instance) {
+      parser.Parse();
+      instance.BestKnownTour = parser.Tour.FirstOrDefault();
+    }
+
+    public PTSPData LoadData(string tspFile, string tourFile, double? bestQuality) {
+      var data = LoadInstance(new TSPLIBParser(tspFile));
+      if (!String.IsNullOrEmpty(tourFile)) {
+        var tourParser = new TSPLIBParser(tourFile);
+        LoadSolution(tourParser, data);
+      }
+      if (bestQuality.HasValue)
+        data.BestKnownQuality = bestQuality.Value;
+      return data;
+    }
+
+  }
+}
