Index: stable/HeuristicLab.Problems.Instances.VehicleRouting.Views/3.4/VRPImportDialog.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting.Views/3.4/VRPImportDialog.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting.Views/3.4/VRPImportDialog.cs	(revision 11931)
@@ -69,5 +69,5 @@
       if (MessageBox.Show("Do you want to open the HeuristicLab wiki website?", "Help",
         MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes) {
-        System.Diagnostics.Process.Start("http://dev.heuristiclab.com/trac/hl/core/wiki/Vehicle%20Routing%20Problem");
+        System.Diagnostics.Process.Start("http://dev.heuristiclab.com/trac.fcgi/wiki/Documentation/Reference/VehicleRoutingProblem");
       }
     }
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting.Views/3.4/VRPInstanceProviderView.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting.Views/3.4/VRPInstanceProviderView.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting.Views/3.4/VRPInstanceProviderView.cs	(revision 11931)
@@ -29,5 +29,5 @@
 namespace HeuristicLab.Problems.Instances.VehicleRouting.Views {
   [View("VRP InstanceProvider View")]
-  [Content(typeof(IProblemInstanceProvider<IVRPData>), IsDefaultView = true)]
+  [Content(typeof(IVRPInstanceProvider<>), IsDefaultView = true)]
   public partial class VRPInstanceProviderView<T> : ProblemInstanceProviderView<T> where T : class, IVRPData {
 
@@ -37,5 +37,5 @@
 
     protected override void importButton_Click(object sender, EventArgs e) {
-      var provider = Content as IVRPInstanceProvider;
+      var provider = Content as IVRPInstanceProvider<T>;
       if (provider != null) {
         using (var dialog = new VRPImportDialog(Content.Name)) {
@@ -54,5 +54,5 @@
 
     protected override void exportButton_Click(object sender, EventArgs e) {
-      var provider = Content as IVRPInstanceProvider;
+      var provider = Content as IVRPInstanceProvider<T>;
       if (provider != null) {
         if (saveFileDialog.ShowDialog(this) == DialogResult.OK) {
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/CordeauFormat/CordeauFormatInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/CordeauFormat/CordeauFormatInstanceProvider.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/CordeauFormat/CordeauFormatInstanceProvider.cs	(revision 11931)
@@ -20,9 +20,13 @@
 #endregion
 
+using System;
+using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
+using System.Linq;
 
 namespace HeuristicLab.Problems.Instances.VehicleRouting {
-  public abstract class CordeauFormatInstanceProvider<T> : VRPInstanceProvider<T> where T : MDCVRPData {
-    protected override T LoadData(Stream stream) {
+  public abstract class CordeauFormatInstanceProvider<TData> : VRPInstanceProvider<TData> where TData : MDCVRPData {
+    protected override TData LoadData(Stream stream) {
       return LoadInstance(new CordeauParser(stream));
     }
@@ -31,9 +35,58 @@
       get { return true; }
     }
-    public override T ImportData(string path) {
+    public override TData ImportData(string path) {
       return LoadInstance(new CordeauParser(path));
     }
 
-    internal abstract T LoadInstance(CordeauParser parser);
+    internal abstract TData LoadInstance(CordeauParser parser);
+
+    protected override void LoadSolution(Stream stream, TData instance) {
+      using (var reader = new StreamReader(stream)) {
+        double costs = double.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
+
+        var toursPerDepotQuery =
+          from line in reader.ReadAllLines()
+          where !string.IsNullOrEmpty(line)
+          let tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
+          let depot = int.Parse(tokens[0])
+          //let vehicle = int.Parse(tokens[1])
+          //let duration = double.Parse(tokens[2], CultureInfo.InvariantCulture)
+          //let load = double.Parse(tokens[3], new CultureInfo.InvariantCulture)
+          let customers = tokens.Skip(4).Where(t => !t.StartsWith("(")).Select(int.Parse)
+          let numberOfCustomers = customers.Count()
+          //let serviceTimes = tokens.Skip(5).Where(t => t.StartsWith("(")).Select(t => double.Parse(t.Trim('(', ')'), CultureInfo.InvariantCulture))
+          let stops = customers.Skip(1).Take(numberOfCustomers - 2).Select(s => s - 1)
+          select new { depot, /*vehicle,*/ stops } into assignment
+          group assignment by assignment.depot;
+
+        var toursPerDepot = toursPerDepotQuery.Select(d => d.Select(v => v.stops.ToArray()).ToArray()).ToArray();
+
+        instance.BestKnownTour = toursPerDepot.SelectMany(depot => depot).ToArray();
+
+        instance.BestKnownTourVehicleAssignment = DetermineTourToVehicleAssignment(toursPerDepot, instance.VehicleDepotAssignment);
+      }
+    }
+
+    private static int[] DetermineTourToVehicleAssignment(int[][][] toursPerDepot, int[] vehicleDepotAssignments) {
+      var usedVehiclesPerDepot = toursPerDepot.Select((d, i) => new { i, d }).ToDictionary(k => k.i, v => v.d.Length);
+      var availableVehiclesPerDepot = vehicleDepotAssignments.GroupBy(a => a).ToDictionary(k => k.Key, v => v.Count());
+
+      var tourToVehicle = new List<int>(vehicleDepotAssignments.Length);
+      var unusedVehicles = new List<int>();
+
+      int vehicle = 0;
+      for (int depot = 0; depot < toursPerDepot.Length; depot++) {
+        int used = usedVehiclesPerDepot[depot];
+        tourToVehicle.AddRange(Enumerable.Range(vehicle, used));
+        vehicle += used;
+
+        int unused = availableVehiclesPerDepot[depot] - used;
+        unusedVehicles.AddRange(Enumerable.Range(vehicle, unused));
+        vehicle += unused;
+      }
+      tourToVehicle.AddRange(unusedVehicles);
+
+      return tourToVehicle.ToArray();
+    }
   }
 }
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/HeuristicLab.Problems.Instances.VehicleRouting-3.4.csproj
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/HeuristicLab.Problems.Instances.VehicleRouting-3.4.csproj	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/HeuristicLab.Problems.Instances.VehicleRouting-3.4.csproj	(revision 11931)
@@ -125,4 +125,5 @@
     <Compile Include="GoldenFormat\GoldenFormatInstanceProvider.cs" />
     <Compile Include="IVRPInstanceProvider.cs" />
+    <Compile Include="StreamReaderHelper.cs" />
     <Compile Include="TaillardFormat\TaillardInstanceProvider.cs" />
     <Compile Include="TaillardFormat\TaillardParser.cs" />
@@ -157,4 +158,7 @@
     <EmbeddedResource Include="Data\CordeauMD.zip" />
     <EmbeddedResource Include="Data\CordeauMDTW.zip" />
+    <EmbeddedResource Include="Data\CordeauMD.opt.zip" />
+    <EmbeddedResource Include="Data\CordeauMDTW.opt.zip" />
+    <EmbeddedResource Include="Data\Homberger.opt.zip" />
     <None Include="Plugin.cs.frame" />
     <Compile Include="Plugin.cs" />
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/IVRPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/IVRPInstanceProvider.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/IVRPInstanceProvider.cs	(revision 11931)
@@ -21,10 +21,10 @@
 
 namespace HeuristicLab.Problems.Instances.VehicleRouting {
-  public interface IVRPInstanceProvider {
+  public interface IVRPInstanceProvider<TData> {
     bool CanImportData { get; }
-    IVRPData Import(string vrpFile, string tourFile);
+    TData Import(string instancePath, string solutionPath);
 
     bool CanExportData { get; }
-    void Export(IVRPData instance, string path);
+    void Export(TData instance, string path);
   }
 }
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/Plugin.cs.frame
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/Plugin.cs.frame	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/Plugin.cs.frame	(revision 11931)
@@ -25,4 +25,5 @@
   [Plugin("HeuristicLab.Problems.Instances.VehicleRouting", "3.4.3.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.Instances.VehicleRouting-3.4.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
   [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
   [PluginDependency("HeuristicLab.Problems.Instances.TSPLIB", "3.3")]
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/SolomonFormat/SolomonFormatInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/SolomonFormat/SolomonFormatInstanceProvider.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/SolomonFormat/SolomonFormatInstanceProvider.cs	(revision 11931)
@@ -20,5 +20,8 @@
 #endregion
 
+using System;
+using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 
 namespace HeuristicLab.Problems.Instances.VehicleRouting {
@@ -54,4 +57,29 @@
       return instance;
     }
+
+    protected override void LoadSolution(Stream stream, CVRPTWData instance) {
+      using (var reader = new StreamReader(stream)) {
+        string instanceName = ExtractValue(reader.ReadLine());
+        string authors = ExtractValue(reader.ReadLine());
+        string date = ExtractValue(reader.ReadLine());
+        string reference = ExtractValue(reader.ReadLine());
+        reader.ReadLine(); // Solution
+
+        var routesQuery =
+          from line in reader.ReadAllLines()
+          where !string.IsNullOrEmpty(line)
+          let tokens = ExtractValue(line).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
+          let stops = tokens.Select(int.Parse).Select(s => s - 1)
+          select stops;
+
+        var routes = routesQuery.Select(s => s.ToArray()).ToArray();
+
+        instance.BestKnownTour = routes;
+      }
+    }
+
+    private static string ExtractValue(string line) {
+      return line.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries).Last().Trim();
+    }
   }
 }
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/StreamReaderHelper.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/StreamReaderHelper.cs	(revision 11931)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/StreamReaderHelper.cs	(revision 11931)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.IO;
+
+namespace HeuristicLab.Problems.Instances.VehicleRouting {
+  internal static class StreamReaderHelper {
+    public static IEnumerable<string> ReadAllLines(this StreamReader reader) {
+      while (!reader.EndOfStream)
+        yield return reader.ReadLine();
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/VRPInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/VRPInstanceProvider.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances.VehicleRouting/3.4/VRPInstanceProvider.cs	(revision 11931)
@@ -26,17 +26,18 @@
 using System.Reflection;
 using System.Text.RegularExpressions;
+using HeuristicLab.Common;
 using ICSharpCode.SharpZipLib.Zip;
 
 namespace HeuristicLab.Problems.Instances.VehicleRouting {
-  public abstract class VRPInstanceProvider<T> : ProblemInstanceProvider<T>, IVRPInstanceProvider where T : IVRPData {
+  public abstract class VRPInstanceProvider<TData> : ProblemInstanceProvider<TData>, IVRPInstanceProvider<TData> where TData : IVRPData {
     protected abstract string FileName { get; }
 
     public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
-      Dictionary<string, string> solutions = new Dictionary<string, string>();
+      var solutions = new Dictionary<string, string>();
       var solutionsArchiveName = GetResourceName(FileName + @"\.opt\.zip");
       if (!String.IsNullOrEmpty(solutionsArchiveName)) {
         using (var solutionsZipFile = new ZipInputStream(GetType().Assembly.GetManifestResourceStream(solutionsArchiveName))) {
           foreach (var entry in GetZipContents(solutionsZipFile))
-            solutions.Add(entry.Substring(0, entry.Length - ".opt".Length) + "." + FileName, entry);
+            solutions.Add(Path.GetFileNameWithoutExtension(entry) + "." + FileName, entry);
         }
       }
@@ -45,6 +46,6 @@
 
       using (var instanceStream = new ZipInputStream(GetType().Assembly.GetManifestResourceStream(instanceArchiveName))) {
-        foreach (var entry in GetZipContents(instanceStream).OrderBy(x => x)) {
-          string solutionEntry = entry.Substring(0, entry.Length - ".opt".Length) + "." + FileName;
+        foreach (var entry in GetZipContents(instanceStream).OrderBy(x => x, new NaturalStringComparer())) {
+          string solutionEntry = Path.GetFileNameWithoutExtension(entry) + "." + FileName;
           yield return new VRPDataDescriptor(Path.GetFileNameWithoutExtension(entry), GetInstanceDescription(), entry, solutions.ContainsKey(solutionEntry) ? solutions[solutionEntry] : String.Empty);
         }
@@ -52,5 +53,5 @@
     }
 
-    public override T LoadData(IDataDescriptor id) {
+    public override TData LoadData(IDataDescriptor id) {
       var descriptor = (VRPDataDescriptor)id;
       var instanceArchiveName = GetResourceName(FileName + @"\.zip");
@@ -76,5 +77,23 @@
     }
 
-    private static void LoadSolution(Stream stream, T instance) {
+    #region IVRPInstanceProvider
+    public TData Import(string vrpFile, string tourFile) {
+      var data = ImportData(vrpFile);
+      if (!String.IsNullOrEmpty(tourFile)) {
+        LoadSolution(tourFile, data);
+      }
+      return data;
+    }
+
+    public void Export(TData instance, string path) {
+      ExportData(instance, path);
+    }
+    #endregion
+
+    protected virtual void LoadSolution(Stream stream, TData instance) {
+      LoadOptFile(stream, instance);
+    }
+
+    private void LoadOptFile(Stream stream, TData instance) {
       List<List<int>> routes = new List<List<int>>();
 
@@ -106,24 +125,20 @@
     }
 
-    public static void LoadSolution(string path, T instance) {
-      using (FileStream stream = new FileStream(path, FileMode.Open)) {
-        LoadSolution(stream, instance);
+    public void LoadSolution(string path, TData instance) {
+      try {
+        using (var stream = new FileStream(path, FileMode.Open)) {
+          LoadSolution(stream, instance);
+        }
+      } catch (Exception) {
+        // new stream necessary because first try already read from stream
+        using (var stream = new FileStream(path, FileMode.Open)) {
+          LoadOptFile(stream, instance); // Fallback to .opt-Format
+        }
       }
     }
 
-    protected abstract T LoadData(Stream stream);
+    protected abstract TData LoadData(Stream stream);
 
-    public IVRPData Import(string vrpFile, string tourFile) {
-      var data = ImportData(vrpFile);
-      if (!String.IsNullOrEmpty(tourFile)) {
-        LoadSolution(tourFile, data);
-      }
-      return data;
-    }
-
-    public void Export(IVRPData instance, string path) {
-      ExportData((T)instance, path);
-    }
-
+    #region Helpers
     protected virtual string GetResourceName(string fileName) {
       return Assembly.GetExecutingAssembly().GetManifestResourceNames()
@@ -141,4 +156,5 @@
       }
     }
+    #endregion
   }
 }
Index: stable/HeuristicLab.Problems.Instances/3.3/Types/VRP/IVRPData.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances/3.3/Types/VRP/IVRPData.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances/3.3/Types/VRP/IVRPData.cs	(revision 11931)
@@ -31,4 +31,5 @@
     double? BestKnownQuality { get; set; }
     int[][] BestKnownTour { get; set; }
+    int[] BestKnownTourVehicleAssignment { get; set; }
   }
 }
Index: stable/HeuristicLab.Problems.Instances/3.3/Types/VRP/VRPData.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances/3.3/Types/VRP/VRPData.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.Instances/3.3/Types/VRP/VRPData.cs	(revision 11931)
@@ -78,4 +78,8 @@
     public int[][] BestKnownTour { get; set; }
     /// <summary>
+    /// Optional! Specifies the used vehicle for a given tour.
+    /// </summary>
+    public int[] BestKnownTourVehicleAssignment { get; set; }
+    /// <summary>
     /// Optional! The quality of the best-known solution.
     /// </summary>
Index: stable/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/PotvinEncoding.cs
===================================================================
--- stable/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/PotvinEncoding.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/PotvinEncoding.cs	(revision 11931)
@@ -36,4 +36,5 @@
     public List<int> Unrouted { get; set; }
 
+    // VehicleAssignment[tour] retreives the assigned vehicle for the given tour
     [Storable]
     public Permutation VehicleAssignment { get; private set; }
Index: stable/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/VRPInterpreter.cs
===================================================================
--- stable/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/VRPInterpreter.cs	(revision 11929)
+++ stable/HeuristicLab.Problems.VehicleRouting/3.4/Interpreters/VRPInterpreter.cs	(revision 11931)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.IO;
 using HeuristicLab.Data;
 using HeuristicLab.Problems.Instances;
@@ -44,4 +45,11 @@
         }
 
+        if (data.BestKnownTourVehicleAssignment != null) {
+          if (data.BestKnownTourVehicleAssignment.Length != solution.VehicleAssignment.Length)
+            throw new InvalidDataException("Number of vehicles of the best known tour does not match the number vehicles of the instance.");
+          for (int i = 0; i < data.BestKnownTourVehicleAssignment.Length; i++)
+            solution.VehicleAssignment[i] = data.BestKnownTourVehicleAssignment[i];
+        }
+
         return solution;
       } else {
@@ -51,5 +59,5 @@
 
     protected abstract IVRPProblemInstance CreateProblemInstance();
-    
+
     public VRPInstanceDescription Interpret(IVRPData data) {
       VRPInstanceDescription result = new VRPInstanceDescription();
Index: stable/HeuristicLab.Tests/HeuristicLab.Problems.VehicleRouting-3.4/VRPInstancesTest.cs
===================================================================
--- stable/HeuristicLab.Tests/HeuristicLab.Problems.VehicleRouting-3.4/VRPInstancesTest.cs	(revision 11929)
+++ stable/HeuristicLab.Tests/HeuristicLab.Problems.VehicleRouting-3.4/VRPInstancesTest.cs	(revision 11931)
@@ -49,5 +49,5 @@
             ((dynamic)vrp).Load(((dynamic)provider).LoadData(instance));
           } catch (Exception exc) {
-            failedInstances.AppendLine(instance + ": " + exc.Message);
+            failedInstances.AppendLine(instance.Name + ": " + exc.Message);
           }
         }
