Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/HeuristicLab.Problems.PTSP-3.3.csproj
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/HeuristicLab.Problems.PTSP-3.3.csproj	(revision 12799)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/HeuristicLab.Problems.PTSP-3.3.csproj	(revision 13202)
@@ -98,4 +98,9 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances.TSPLIB-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Problems.Instances.TSPLIB-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
     <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -105,4 +110,5 @@
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
+    <Reference Include="System.IO.Compression" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
@@ -112,4 +118,6 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="PTSPData.cs" />
+    <Compile Include="PTSPLIBInstanceProvider.cs" />
     <None Include="Properties\AssemblyInfo.cs.frame" />
     <None Include="Plugin.cs.frame" />
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSP.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSP.cs	(revision 12799)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSP.cs	(revision 13202)
@@ -20,19 +20,12 @@
 #endregion
 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
 using HeuristicLab.Optimization;
-using HeuristicLab.PluginInfrastructure;
-using HeuristicLab.Core;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.Instances;
-using HeuristicLab.Encodings.PermutationEncoding;
-using HeuristicLab.Common;
-using HeuristicLab.Parameters;
-using HeuristicLab.Data;
-using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.PTSP {
@@ -59,5 +52,5 @@
       get { return (ValueParameter<DoubleArray>)Parameters["ProbabilityMatrix"]; }
     }
-    
+
 
     #endregion
@@ -84,7 +77,7 @@
       set { ProbabilityMatrixParameter.Value = value; }
     }
-    
+
     #endregion
-    
+
 
     public override bool Maximization {
@@ -112,6 +105,6 @@
       });
 
-      ProbabilityMatrix = new DoubleArray(new double[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
-      
+      ProbabilityMatrix = new DoubleArray(new double[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
+
     }
 
@@ -134,16 +127,8 @@
         BestKnownSolution = new Permutation(PermutationTypes.RelativeUndirected, data.BestKnownTour);
       }
-      
-      bool clearCoordinates = false, clearDistanceMatrix = false;
-      if (data.Coordinates != null && data.Coordinates.GetLength(0) > 0)
-        Coordinates = new DoubleMatrix(data.Coordinates);
-      else clearCoordinates = true;
 
-      // reset them after assigning the evaluator
-      if (clearCoordinates) Coordinates = null;
-      if (clearDistanceMatrix) DistanceMatrix = null;
+      Coordinates = data.Coordinates != null && data.Coordinates.GetLength(0) > 0 ? new DoubleMatrix(data.Coordinates) : null;
+      DistanceMatrix = new DistanceMatrix(data.GetDistanceMatrix());
 
-      DistanceMatrix = new DistanceMatrix(data.GetDistanceMatrix());
-      
       Encoding.Length = data.Dimension;
 
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPData.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPData.cs	(revision 13202)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPData.cs	(revision 13202)
@@ -0,0 +1,11 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Problems.Instances;
+
+namespace HeuristicLab.Problems.PTSP {
+  public class PTSPData : TSPData {
+    public double[] Probabilities { get; set; }
+  }
+}
Index: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPLIBInstanceProvider.cs
===================================================================
--- branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPLIBInstanceProvider.cs	(revision 13202)
+++ branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPLIBInstanceProvider.cs	(revision 13202)
@@ -0,0 +1,142 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using HeuristicLab.Problems.Instances;
+using HeuristicLab.Problems.Instances.TSPLIB;
+
+namespace HeuristicLab.Problems.PTSP {
+  public class PTSPLIBInstanceProvider : TSPLIBInstanceProvider<PTSPData> {
+
+    public override string Name {
+      get { return "(P)TSPLIB (symmetric TSP)"; }
+    }
+
+    public override string Description {
+      get { return "Adaption of the Traveling Salesman Problem Library for probabilistic instances"; }
+    }
+
+    protected override string FileExtension { get { return "tsp"; } }
+
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      Dictionary<string, string> solutions = new Dictionary<string, string>();
+      var solutionsArchiveName = GetResourceName(FileExtension + @"\.opt\.tour\.zip");
+      if (!String.IsNullOrEmpty(solutionsArchiveName)) {
+        using (var solutionsZipFile = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(solutionsArchiveName), ZipArchiveMode.Read)) {
+          foreach (var entry in solutionsZipFile.Entries)
+            solutions.Add(entry.Name.Substring(0, entry.Name.Length - ".opt.tour".Length) + "." + FileExtension, entry.Name);
+        }
+      }
+      var instanceArchiveName = GetResourceName(FileExtension + @"\.zip");
+      if (String.IsNullOrEmpty(instanceArchiveName)) yield break;
+
+      using (var instanceStream = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(instanceArchiveName), ZipArchiveMode.Read)) {
+        foreach (var entry in instanceStream.Entries.Select(x => x.Name).OrderBy(x => x)) {
+          yield return new PTSPDataDescriptor(Path.GetFileNameWithoutExtension(entry), GetInstanceDescription(), entry, solutions.ContainsKey(entry) ? solutions[entry] : String.Empty);
+        }
+      }
+    }
+
+    public override PTSPData LoadData(IDataDescriptor id) {
+      var descriptor = (PTSPDataDescriptor)id;
+      var instanceArchiveName = GetResourceName(FileExtension + @"\.zip");
+      using (var instancesZipFile = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(instanceArchiveName), ZipArchiveMode.Read)) {
+        var entry = instancesZipFile.GetEntry(descriptor.InstanceIdentifier);
+        var stream = entry.Open();
+        var parser = new TSPLIBParser(stream);
+        var instance = LoadInstance(parser);
+
+        if (!String.IsNullOrEmpty(descriptor.SolutionIdentifier)) {
+          var solutionsArchiveName = GetResourceName(FileExtension + @"\.opt\.tour\.zip");
+          using (var solutionsZipFile = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(solutionsArchiveName), ZipArchiveMode.Read)) {
+            entry = solutionsZipFile.GetEntry(descriptor.SolutionIdentifier);
+            stream = entry.Open();
+            parser = new TSPLIBParser(stream);
+            LoadSolution(parser, instance);
+          }
+        }
+
+        return instance;
+      }
+    }
+
+    protected override PTSPData LoadInstance(TSPLIBParser parser) {
+      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 ?? 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.");
+      }
+
+      // use own hash function in case the implementation of String.GetHashCode() changes
+      // ... and hope that System.Random doesn't change
+      var random = new System.Random(Hash(parser.Name));
+      instance.Probabilities = Enumerable.Range(0, parser.Dimension).Select(x => random.NextDouble() * 0.8 + 0.1).ToArray();
+      instance.Name = parser.Name;
+      instance.Description = parser.Comment
+        + Environment.NewLine + Environment.NewLine
+        + GetInstanceDescription();
+      return instance;
+    }
+
+    protected override void LoadSolution(TSPLIBParser parser, PTSPData instance) {
+      // the TSP optimal tour isn't necessarily the PTSP optimal tour
+    }
+
+    public PTSPData LoadData(string tspFile, double? bestQuality) {
+      var data = LoadInstance(new TSPLIBParser(tspFile));
+      if (bestQuality.HasValue)
+        data.BestKnownQuality = bestQuality.Value;
+      return data;
+    }
+
+    private int Hash(string s) {
+      var h = 3571;
+      unchecked {
+        for (var i = 0; i < s.Length; i++)
+          h = h * 31 + s[i];
+      }
+      return h;
+    }
+  }
+
+  internal class PTSPDataDescriptor : IDataDescriptor {
+    public string Name { get; internal set; }
+    public string Description { get; internal set; }
+
+    internal string InstanceIdentifier { get; set; }
+    internal string SolutionIdentifier { get; set; }
+
+    internal PTSPDataDescriptor(string name, string description, string instanceIdentifier, string solutionIdentifier) {
+      this.Name = name;
+      this.Description = description;
+      this.InstanceIdentifier = instanceIdentifier;
+      this.SolutionIdentifier = solutionIdentifier;
+    }
+  }
+}
