Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/HeuristicLab.Problems.Instances.TSPLIB-3.3.csproj
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/HeuristicLab.Problems.Instances.TSPLIB-3.3.csproj	(revision 13316)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/HeuristicLab.Problems.Instances.TSPLIB-3.3.csproj	(revision 13486)
@@ -115,8 +115,13 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="TSPLIBHeterogeneousPTSPDataDescriptor.cs" />
+    <Compile Include="TSPLIBHomogeneousPTSPDataDescriptor.cs" />
+    <Compile Include="TSPLIBHeterogeneousPTSPInstanceProvider.cs" />
+    <Compile Include="TSPLIBPTSPInstanceProvider.cs" />
     <Compile Include="TSPLIBInstanceProvider.cs" />
     <Compile Include="TSPLIBATSPInstanceProvider.cs" />
     <Compile Include="TSPLIBCVRPInstanceProvider.cs" />
     <Compile Include="TSPLIBDataDescriptor.cs" />
+    <Compile Include="TSPLIBHomogeneousPTSPInstanceProvider.cs" />
     <Compile Include="TSPLIBTSPInstanceProvider.cs" />
     <Compile Include="TSPLIBParser.cs" />
@@ -150,5 +155,4 @@
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBATSPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBATSPInstanceProvider.cs	(revision 13316)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBATSPInstanceProvider.cs	(revision 13486)
@@ -36,5 +36,5 @@
     protected override string FileExtension { get { return "atsp"; } }
 
-    protected override ATSPData LoadInstance(TSPLIBParser parser) {
+    protected override ATSPData LoadInstance(TSPLIBParser parser, IDataDescriptor descriptor = null) {
       var instance = new ATSPData();
 
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBCVRPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBCVRPInstanceProvider.cs	(revision 13316)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBCVRPInstanceProvider.cs	(revision 13486)
@@ -36,5 +36,5 @@
     protected override string FileExtension { get { return "vrp"; } }
 
-    protected override CVRPData LoadInstance(TSPLIBParser parser) {
+    protected override CVRPData LoadInstance(TSPLIBParser parser, IDataDescriptor descriptor = null) {
       parser.Parse();
       var instance = new CVRPData();
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPDataDescriptor.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPDataDescriptor.cs	(revision 13486)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPDataDescriptor.cs	(revision 13486)
@@ -0,0 +1,36 @@
+﻿#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
+
+
+namespace HeuristicLab.Problems.Instances.TSPLIB {
+  internal class TSPLIBHeterogeneousPTSPDataDescriptor : TSPLIBDataDescriptor {
+    public int Seed { get; internal set; }
+
+    internal TSPLIBHeterogeneousPTSPDataDescriptor(string name, string description, string instanceIdentifier, string solutionIdentifier, int seed)
+      : base(name, description, instanceIdentifier, solutionIdentifier) {
+      this.Name = name;
+      this.Description = description;
+      this.InstanceIdentifier = instanceIdentifier;
+      this.SolutionIdentifier = solutionIdentifier;
+      this.Seed = seed;
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPInstanceProvider.cs	(revision 13486)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHeterogeneousPTSPInstanceProvider.cs	(revision 13486)
@@ -0,0 +1,103 @@
+﻿#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.Collections.Generic;
+using System.Linq;
+
+namespace HeuristicLab.Problems.Instances.TSPLIB {
+  public class TSPLIBHeterogeneousPTSPInstanceProvider : TSPLIBPTSPInstanceProvider {
+
+    public override string Name {
+      get { return "TSPLIB (heterogeneous symmetric PTSP)"; }
+    }
+
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      foreach (var desc in base.GetDataDescriptors().OfType<TSPLIBDataDescriptor>()) {
+        desc.SolutionIdentifier = null;
+        yield return desc;
+      }
+    }
+
+    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; }
+      }
+
+      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;
+      }
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPDataDescriptor.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPDataDescriptor.cs	(revision 13486)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPDataDescriptor.cs	(revision 13486)
@@ -0,0 +1,35 @@
+﻿#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
+
+namespace HeuristicLab.Problems.Instances.TSPLIB {
+  internal class TSPLIBHomogeneousPTSPDataDescriptor : TSPLIBDataDescriptor {
+    public double Probability { get; internal set; }
+
+    internal TSPLIBHomogeneousPTSPDataDescriptor(string name, string description, string instanceIdentifier, string solutionIdentifier, double probability)
+      : base(name, description, instanceIdentifier, solutionIdentifier) {
+      this.Name = name;
+      this.Description = description;
+      this.InstanceIdentifier = instanceIdentifier;
+      this.SolutionIdentifier = solutionIdentifier;
+      this.Probability = probability;
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPInstanceProvider.cs	(revision 13486)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBHomogeneousPTSPInstanceProvider.cs	(revision 13486)
@@ -0,0 +1,54 @@
+﻿#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.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace HeuristicLab.Problems.Instances.TSPLIB {
+  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 {
+      get { return "TSPLIB (homogeneous symmetric PTSP)"; }
+    }
+
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      var tspDescriptors = base.GetDataDescriptors().OfType<TSPLIBDataDescriptor>();
+      foreach (var desc in tspDescriptors) {
+        foreach (var p in Probabilities) {
+          yield return new TSPLIBHomogeneousPTSPDataDescriptor(
+            desc.Name + "-" + p.ToString(CultureInfo.InvariantCulture.NumberFormat),
+            desc.Description,
+            desc.InstanceIdentifier,
+            p == 1.0 ? desc.SolutionIdentifier : null,
+            p);
+        }
+      }
+    }
+
+    protected override double[] GetProbabilities(IDataDescriptor descriptor, PTSPData instance) {
+      var ptspDesc = descriptor as TSPLIBHomogeneousPTSPDataDescriptor;
+      return ptspDesc != null ? Enumerable.Range(0, instance.Dimension).Select(_ => ptspDesc.Probability).ToArray()
+                              : Enumerable.Range(0, instance.Dimension).Select(_ => 0.5).ToArray();
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBInstanceProvider.cs	(revision 13316)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBInstanceProvider.cs	(revision 13486)
@@ -45,5 +45,5 @@
     protected abstract string FileExtension { get; }
 
-    protected abstract T LoadInstance(TSPLIBParser parser);
+    protected abstract T LoadInstance(TSPLIBParser parser, IDataDescriptor descriptor = null);
     protected abstract void LoadSolution(TSPLIBParser parser, T instance);
 
@@ -74,5 +74,5 @@
         var stream = entry.Open();
         var parser = new TSPLIBParser(stream);
-        var instance = LoadInstance(parser);
+        var instance = LoadInstance(parser, id);
 
         if (!String.IsNullOrEmpty(descriptor.SolutionIdentifier)) {
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBPTSPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBPTSPInstanceProvider.cs	(revision 13486)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBPTSPInstanceProvider.cs	(revision 13486)
@@ -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;
+    }
+
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs	(revision 13316)
+++ stable/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs	(revision 13486)
@@ -37,5 +37,5 @@
     protected override string FileExtension { get { return "tsp"; } }
 
-    protected override TSPData LoadInstance(TSPLIBParser parser) {
+    protected override TSPData 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.");
