Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/HeuristicLab.Problems.VehicleRouting.Views-3.4.csproj
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/HeuristicLab.Problems.VehicleRouting.Views-3.4.csproj	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/HeuristicLab.Problems.VehicleRouting.Views-3.4.csproj	(revision 4860)
@@ -125,4 +125,10 @@
       <DependentUpon>SingleDepotVRPView.cs</DependentUpon>
     </Compile>
+    <Compile Include="VRPImportDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="VRPImportDialog.Designer.cs">
+      <DependentUpon>VRPImportDialog.cs</DependentUpon>
+    </Compile>
     <Compile Include="VRPProblemInstanceView.cs">
       <SubType>UserControl</SubType>
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VRPImportDialog.Designer.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VRPImportDialog.Designer.cs	(revision 4860)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VRPImportDialog.Designer.cs	(revision 4860)
@@ -0,0 +1,215 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.VehicleRouting.Views {
+  partial class VRPImportDialog {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.okButton = new System.Windows.Forms.Button();
+      this.cancelButton = new System.Windows.Forms.Button();
+      this.openVRPFileDialog = new System.Windows.Forms.OpenFileDialog();
+      this.tspFileLabel = new System.Windows.Forms.Label();
+      this.openVRPFileButton = new System.Windows.Forms.Button();
+      this.tspFileTextBox = new System.Windows.Forms.TextBox();
+      this.tourFileLabel = new System.Windows.Forms.Label();
+      this.openTourFileButton = new System.Windows.Forms.Button();
+      this.tourFileTextBox = new System.Windows.Forms.TextBox();
+      this.openTourFileDialog = new System.Windows.Forms.OpenFileDialog();
+      this.clearTourFileButton = new System.Windows.Forms.Button();
+      this.SuspendLayout();
+      // 
+      // okButton
+      // 
+      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
+      this.okButton.Enabled = false;
+      this.okButton.Location = new System.Drawing.Point(422, 69);
+      this.okButton.Name = "okButton";
+      this.okButton.Size = new System.Drawing.Size(75, 23);
+      this.okButton.TabIndex = 9;
+      this.okButton.Text = "&OK";
+      this.okButton.UseVisualStyleBackColor = true;
+      // 
+      // cancelButton
+      // 
+      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+      this.cancelButton.Location = new System.Drawing.Point(499, 69);
+      this.cancelButton.Name = "cancelButton";
+      this.cancelButton.Size = new System.Drawing.Size(75, 23);
+      this.cancelButton.TabIndex = 10;
+      this.cancelButton.Text = "&Cancel";
+      this.cancelButton.UseVisualStyleBackColor = true;
+      // 
+      // openVRPFileDialog
+      // 
+      this.openVRPFileDialog.DefaultExt = "vrp";
+      this.openVRPFileDialog.FileName = "vrp";
+      this.openVRPFileDialog.Filter = "TSPLib Format|*.vrp|Solomon Format|*.txt|ORLib Format|*.txt";
+      this.openVRPFileDialog.Title = "Open TSP File";
+      // 
+      // tspFileLabel
+      // 
+      this.tspFileLabel.AutoSize = true;
+      this.tspFileLabel.Location = new System.Drawing.Point(12, 15);
+      this.tspFileLabel.Name = "tspFileLabel";
+      this.tspFileLabel.Size = new System.Drawing.Size(51, 13);
+      this.tspFileLabel.TabIndex = 0;
+      this.tspFileLabel.Text = "&VRP File:";
+      // 
+      // openVRPFileButton
+      // 
+      this.openVRPFileButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.openVRPFileButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Open;
+      this.openVRPFileButton.Location = new System.Drawing.Point(520, 10);
+      this.openVRPFileButton.Name = "openVRPFileButton";
+      this.openVRPFileButton.Size = new System.Drawing.Size(24, 24);
+      this.openVRPFileButton.TabIndex = 2;
+      this.openVRPFileButton.UseVisualStyleBackColor = true;
+      this.openVRPFileButton.Click += new System.EventHandler(this.openVRPFileButton_Click);
+      // 
+      // tspFileTextBox
+      // 
+      this.tspFileTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.tspFileTextBox.Enabled = false;
+      this.tspFileTextBox.Location = new System.Drawing.Point(136, 12);
+      this.tspFileTextBox.Name = "tspFileTextBox";
+      this.tspFileTextBox.ReadOnly = true;
+      this.tspFileTextBox.Size = new System.Drawing.Size(378, 20);
+      this.tspFileTextBox.TabIndex = 1;
+      // 
+      // tourFileLabel
+      // 
+      this.tourFileLabel.AutoSize = true;
+      this.tourFileLabel.Location = new System.Drawing.Point(12, 41);
+      this.tourFileLabel.Name = "tourFileLabel";
+      this.tourFileLabel.Size = new System.Drawing.Size(119, 13);
+      this.tourFileLabel.TabIndex = 5;
+      this.tourFileLabel.Text = "&Optimal VRP Tours File:";
+      // 
+      // openTourFileButton
+      // 
+      this.openTourFileButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.openTourFileButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Open;
+      this.openTourFileButton.Location = new System.Drawing.Point(520, 35);
+      this.openTourFileButton.Name = "openTourFileButton";
+      this.openTourFileButton.Size = new System.Drawing.Size(24, 24);
+      this.openTourFileButton.TabIndex = 7;
+      this.openTourFileButton.UseVisualStyleBackColor = true;
+      this.openTourFileButton.Click += new System.EventHandler(this.openTourFileButton_Click);
+      // 
+      // tourFileTextBox
+      // 
+      this.tourFileTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.tourFileTextBox.Enabled = false;
+      this.tourFileTextBox.Location = new System.Drawing.Point(136, 38);
+      this.tourFileTextBox.Name = "tourFileTextBox";
+      this.tourFileTextBox.ReadOnly = true;
+      this.tourFileTextBox.Size = new System.Drawing.Size(378, 20);
+      this.tourFileTextBox.TabIndex = 6;
+      // 
+      // openTourFileDialog
+      // 
+      this.openTourFileDialog.DefaultExt = "opt";
+      this.openTourFileDialog.FileName = "tour";
+      this.openTourFileDialog.Filter = "Optimal VRP Tour Files|*.opt";
+      this.openTourFileDialog.SupportMultiDottedExtensions = true;
+      this.openTourFileDialog.Title = "Open Optimal TSP Tour File";
+      // 
+      // clearTourFileButton
+      // 
+      this.clearTourFileButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.clearTourFileButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Remove;
+      this.clearTourFileButton.Location = new System.Drawing.Point(550, 35);
+      this.clearTourFileButton.Name = "clearTourFileButton";
+      this.clearTourFileButton.Size = new System.Drawing.Size(24, 24);
+      this.clearTourFileButton.TabIndex = 8;
+      this.clearTourFileButton.UseVisualStyleBackColor = true;
+      this.clearTourFileButton.Click += new System.EventHandler(this.clearTourFileButton_Click);
+      // 
+      // VRPImportDialog
+      // 
+      this.AcceptButton = this.okButton;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.CancelButton = this.cancelButton;
+      this.ClientSize = new System.Drawing.Size(586, 104);
+      this.Controls.Add(this.tourFileTextBox);
+      this.Controls.Add(this.tspFileTextBox);
+      this.Controls.Add(this.clearTourFileButton);
+      this.Controls.Add(this.openTourFileButton);
+      this.Controls.Add(this.openVRPFileButton);
+      this.Controls.Add(this.tourFileLabel);
+      this.Controls.Add(this.tspFileLabel);
+      this.Controls.Add(this.cancelButton);
+      this.Controls.Add(this.okButton);
+      this.HelpButton = true;
+      this.MaximizeBox = false;
+      this.MinimizeBox = false;
+      this.Name = "VRPImportDialog";
+      this.ShowIcon = false;
+      this.ShowInTaskbar = false;
+      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+      this.Text = "Import VRP";
+      this.HelpButtonClicked += new System.ComponentModel.CancelEventHandler(this.VRPImportDialog_HelpButtonClicked);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button okButton;
+    private System.Windows.Forms.Button cancelButton;
+    private System.Windows.Forms.OpenFileDialog openVRPFileDialog;
+    private System.Windows.Forms.Label tspFileLabel;
+    private System.Windows.Forms.Button openVRPFileButton;
+    private System.Windows.Forms.TextBox tspFileTextBox;
+    private System.Windows.Forms.Label tourFileLabel;
+    private System.Windows.Forms.Button openTourFileButton;
+    private System.Windows.Forms.TextBox tourFileTextBox;
+    private System.Windows.Forms.OpenFileDialog openTourFileDialog;
+    private System.Windows.Forms.Button clearTourFileButton;
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VRPImportDialog.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VRPImportDialog.cs	(revision 4860)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VRPImportDialog.cs	(revision 4860)
@@ -0,0 +1,85 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.ComponentModel;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.VehicleRouting.Views {
+  public enum VRPFormat { Empty, TSPLib, Solomon, ORLib }
+
+  public sealed partial class VRPImportDialog : Form {
+    private string vrpFileName;
+    public string VRPFileName {
+      get { return vrpFileName; }
+    }
+    private string tourFileName;
+    public string TourFileName {
+      get { return tourFileName; }
+    }
+    private VRPFormat format;
+    public VRPFormat Format {
+      get { return format; }
+    }
+
+    public VRPImportDialog() {
+      InitializeComponent();
+      vrpFileName = string.Empty;
+      tourFileName = string.Empty;
+      format = VRPFormat.Empty;
+    }
+
+    private void openVRPFileButton_Click(object sender, EventArgs e) {
+      if (openVRPFileDialog.ShowDialog(this) == DialogResult.OK) {
+        tspFileTextBox.Text = openVRPFileDialog.FileName;
+        tspFileTextBox.Enabled = true;
+        vrpFileName = openVRPFileDialog.FileName;
+        okButton.Enabled = true;
+
+        tourFileTextBox.Text = string.Empty;
+        tourFileName = string.Empty;
+
+        format = (VRPFormat)(openVRPFileDialog.FilterIndex);
+      }
+    }
+    private void openTourFileButton_Click(object sender, EventArgs e) {
+      if (openTourFileDialog.ShowDialog(this) == DialogResult.OK) {
+        tourFileTextBox.Text = openTourFileDialog.FileName;
+        tourFileTextBox.Enabled = true;
+        tourFileName = openTourFileDialog.FileName;
+      }
+    }
+    private void clearTourFileButton_Click(object sender, EventArgs e) {
+      tourFileTextBox.Text = string.Empty;
+      tourFileTextBox.Enabled = false;
+      tourFileName = string.Empty;
+    }
+
+    private void VRPImportDialog_HelpButtonClicked(object sender, CancelEventArgs e) {
+      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");
+      }
+    }
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VehicleRoutingProblemView.Designer.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VehicleRoutingProblemView.Designer.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VehicleRoutingProblemView.Designer.cs	(revision 4860)
@@ -25,6 +25,4 @@
     private void InitializeComponent() {
       this.importButton = new System.Windows.Forms.Button();
-      this.importButton2 = new System.Windows.Forms.Button();
-      this.importButton3 = new System.Windows.Forms.Button();
       this.parameterCollectionView = new HeuristicLab.Core.Views.ParameterCollectionView();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
@@ -38,31 +36,13 @@
       // importButton
       // 
+      this.importButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
       this.importButton.Location = new System.Drawing.Point(0, 55);
       this.importButton.Name = "importButton";
-      this.importButton.Size = new System.Drawing.Size(139, 23);
+      this.importButton.Size = new System.Drawing.Size(490, 23);
       this.importButton.TabIndex = 5;
-      this.importButton.Text = "Import from Solomon";
+      this.importButton.Text = "Import";
       this.importButton.UseVisualStyleBackColor = true;
       this.importButton.Click += new System.EventHandler(this.importButton_Click);
-      // 
-      // importButton2
-      // 
-      this.importButton2.Location = new System.Drawing.Point(145, 55);
-      this.importButton2.Name = "importButton2";
-      this.importButton2.Size = new System.Drawing.Size(126, 23);
-      this.importButton2.TabIndex = 7;
-      this.importButton2.Text = "Import from TSPLib";
-      this.importButton2.UseVisualStyleBackColor = true;
-      this.importButton2.Click += new System.EventHandler(this.importButton2_Click);
-      // 
-      // importButton3
-      // 
-      this.importButton3.Location = new System.Drawing.Point(277, 55);
-      this.importButton3.Name = "importButton3";
-      this.importButton3.Size = new System.Drawing.Size(131, 23);
-      this.importButton3.TabIndex = 8;
-      this.importButton3.Text = "Import from ORLib";
-      this.importButton3.UseVisualStyleBackColor = true;
-      this.importButton3.Click += new System.EventHandler(this.importButton3_Click);
       // 
       // parameterCollectionView
@@ -83,17 +63,13 @@
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.Controls.Add(this.parameterCollectionView);
-      this.Controls.Add(this.importButton3);
-      this.Controls.Add(this.importButton2);
       this.Controls.Add(this.importButton);
       this.Name = "VehicleRoutingProblemView";
       this.Size = new System.Drawing.Size(490, 352);
       this.Controls.SetChildIndex(this.importButton, 0);
-      this.Controls.SetChildIndex(this.importButton2, 0);
-      this.Controls.SetChildIndex(this.importButton3, 0);
+      this.Controls.SetChildIndex(this.parameterCollectionView, 0);
       this.Controls.SetChildIndex(this.nameTextBox, 0);
       this.Controls.SetChildIndex(this.nameLabel, 0);
       this.Controls.SetChildIndex(this.descriptionLabel, 0);
       this.Controls.SetChildIndex(this.descriptionTextBox, 0);
-      this.Controls.SetChildIndex(this.parameterCollectionView, 0);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.ResumeLayout(false);
@@ -105,6 +81,4 @@
 
     private System.Windows.Forms.Button importButton;
-    private System.Windows.Forms.Button importButton2;
-    private System.Windows.Forms.Button importButton3;
     private Core.Views.ParameterCollectionView parameterCollectionView;
   }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VehicleRoutingProblemView.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VehicleRoutingProblemView.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting.Views/3.4/VehicleRoutingProblemView.cs	(revision 4860)
@@ -26,4 +26,5 @@
 using HeuristicLab.Core.Views;
 using HeuristicLab.Core;
+using HeuristicLab.PluginInfrastructure;
 
 namespace HeuristicLab.Problems.VehicleRouting.Views {
@@ -31,4 +32,6 @@
   [Content(typeof(VehicleRoutingProblem), true)]
   public partial class VehicleRoutingProblemView : NamedItemView {
+    private VRPImportDialog vrpImportDialog; 
+
     public new VehicleRoutingProblem Content {
       get { return (VehicleRoutingProblem)base.Content; }
@@ -59,33 +62,34 @@
       base.SetEnabledStateOfControls();
       parameterCollectionView.Enabled = Content != null;
-      importButton.Enabled = importButton2.Enabled = importButton3.Enabled = Content != null && !ReadOnly;
+      importButton.Enabled = Content != null && !ReadOnly;
     }
 
     private void importButton_Click(object sender, EventArgs e) {
-      OpenFileDialog dialog = new OpenFileDialog();
-      dialog.Filter = "Solomon files (*.txt)|*.txt";
+      if (vrpImportDialog == null) vrpImportDialog = new VRPImportDialog();
 
-      if (dialog.ShowDialog() == DialogResult.OK) {
-        Content.ImportFromSolomon(dialog.FileName);
+      if (vrpImportDialog.ShowDialog(this) == DialogResult.OK) {
+        try {
+          switch (vrpImportDialog.Format) {
+            case VRPFormat.TSPLib:
+              Content.ImportFromTSPLib(vrpImportDialog.VRPFileName);
+              break;
+
+            case VRPFormat.Solomon:
+              Content.ImportFromSolomon(vrpImportDialog.VRPFileName);
+              break;
+
+            case VRPFormat.ORLib:
+              Content.ImportFromORLib(vrpImportDialog.VRPFileName);
+              break;
+          }
+
+          if (!string.IsNullOrEmpty(vrpImportDialog.TourFileName))
+            Content.ImportSolution(vrpImportDialog.TourFileName); 
+        }
+        catch (Exception ex) {
+          ErrorHandling.ShowErrorDialog(this, ex);
+        }
       }
-    }
-
-    private void importButton2_Click(object sender, EventArgs e) {
-      OpenFileDialog dialog = new OpenFileDialog();
-      dialog.Filter = "TSPLib files (*.vrp)|*.vrp";
-
-      if (dialog.ShowDialog() == DialogResult.OK) {
-        Content.ImportFromTSPLib(dialog.FileName);
-      }
-    }
-
-    private void importButton3_Click(object sender, EventArgs e) {
-      OpenFileDialog dialog = new OpenFileDialog();
-      dialog.Filter = "ORLib files (*.txt)|*.txt";
-
-      if (dialog.ShowDialog() == DialogResult.OK) {
-        Content.ImportFromORLib(dialog.FileName);
-      }
-    }    
+    }  
   }
 }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/BestVRPSolutionAnalyzer.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/BestVRPSolutionAnalyzer.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Analyzer/BestSolution/BestVRPSolutionAnalyzer.cs	(revision 4860)
@@ -62,4 +62,11 @@
     }
 
+    public LookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public LookupParameter<VRPSolution> BestKnownSolutionParameter {
+      get { return (LookupParameter<VRPSolution>)Parameters["BestKnownSolution"]; }
+    }
+
     [StorableConstructor]
     private BestVRPSolutionAnalyzer(bool deserializing) : base(deserializing) { }
@@ -69,4 +76,7 @@
         Parameters.Add(new LookupParameter<IVRPProblemInstance>("ProblemInstance", "The problem instance."));
         Parameters.Add(new ScopeTreeLookupParameter<IVRPEncoding>("VRPTours", "The VRP tours which should be evaluated."));
+
+        Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+        Parameters.Add(new LookupParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
 
         Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the VRP solutions which should be analyzed."));
@@ -86,4 +96,16 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      #region Backwards Compatibility
+      if (!Parameters.ContainsKey("BestKnownQuality")) {
+        Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+      }
+      if (!Parameters.ContainsKey("BestKnownSolution")) {
+        Parameters.Add(new LookupParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
+      }
+      #endregion
+    }
+
     public override IOperation Apply() {
       IVRPProblemInstance problemInstance = ProblemInstanceParameter.ActualValue;
@@ -96,4 +118,6 @@
 
       int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
+      DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
 
       IVRPEncoding best = solutions[i].Clone() as IVRPEncoding;
@@ -116,4 +140,10 @@
       }
 
+      if (bestKnownQuality == null ||
+          qualities[i].Value < bestKnownQuality.Value) {
+        BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value);
+        BestKnownSolutionParameter.ActualValue = (VRPSolution)solution.Clone();
+      }
+
       return base.Apply();
     }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/HeuristicLab.Problems.VehicleRouting-3.4.csproj	(revision 4860)
@@ -227,4 +227,5 @@
     <Compile Include="Interfaces\IVRPEncoding.cs" />
     <Compile Include="Interfaces\IVRPProblemInstance.cs" />
+    <Compile Include="SolutionParser.cs" />
     <Compile Include="Variants\Capacitated\Heterogenous\IHeterogenousCapacitatedProblemInstance.cs" />
     <Compile Include="Variants\Capacitated\Heterogenous\IHeterogenousCapacitatedOperator.cs" />
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Interfaces/IVRPProblemInstance.cs	(revision 4860)
@@ -32,4 +32,6 @@
     IValueParameter<IVRPEvaluator> EvaluatorParameter { get; }
     IValueParameter<IVRPCreator> SolutionCreatorParameter { get; }
+    IValueParameter<DoubleValue> BestKnownQualityParameter { get; }
+    IValueParameter<VRPSolution> BestKnownSolutionParameter { get; }
     IEnumerable<IOperator> Operators { get; }
 
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPProblemInstance.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPProblemInstance.cs	(revision 4860)
@@ -77,4 +77,6 @@
       Parameters.Add(new ValueParameter<DoubleValue>("Capacity", "The capacity of each vehicle.", new DoubleValue(0)));
       Parameters.Add(new ValueParameter<DoubleValue>("EvalOverloadPenalty", "The overload penalty considered in the evaluation.", new DoubleValue(100)));
+
+      AttachEventHandlers();
     }
 
@@ -85,5 +87,35 @@
     protected CVRPProblemInstance(CVRPProblemInstance original, Cloner cloner)
       : base(original, cloner) {
+        AttachEventHandlers();
     }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      CapacityParameter.ValueChanged += new EventHandler(CapacityParameter_ValueChanged);
+      CapacityParameter.Value.ValueChanged += new EventHandler(Capacity_ValueChanged);
+      OverloadPenaltyParameter.ValueChanged += new EventHandler(OverloadPenaltyParameter_ValueChanged);
+      OverloadPenaltyParameter.Value.ValueChanged += new EventHandler(OverloadPenalty_ValueChanged);
+    }
+
+    #region Event handlers
+    void CapacityParameter_ValueChanged(object sender, EventArgs e) {
+      CapacityParameter.Value.ValueChanged += new EventHandler(Capacity_ValueChanged);
+      BestKnownSolution = null;
+    }
+    void Capacity_ValueChanged(object sender, EventArgs e) {
+      BestKnownSolution = null;
+    }
+    void OverloadPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      OverloadPenaltyParameter.Value.ValueChanged += new EventHandler(OverloadPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void OverloadPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
   }
 }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWProblemInstance.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/SingleDepotVRP/CVRP/CVRPTW/CVRPTWProblemInstance.cs	(revision 4860)
@@ -103,4 +103,6 @@
       Parameters.Add(new ValueParameter<DoubleValue>("EvalTimeFactor", "The time factor considered in the evaluation.", new DoubleValue(0)));
       Parameters.Add(new ValueParameter<DoubleValue>("EvalTardinessPenalty", "The tardiness penalty considered in the evaluation.", new DoubleValue(100)));
+
+      AttachEventHandlers();
     }
 
@@ -111,5 +113,35 @@
     protected CVRPTWProblemInstance(CVRPTWProblemInstance original, Cloner cloner)
       : base(original, cloner) {
+        AttachEventHandlers();
     }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      TardinessPenaltyParameter.ValueChanged += new EventHandler(TardinessPenaltyParameter_ValueChanged);
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      TimeFactorParameter.ValueChanged += new EventHandler(TimeFactorParameter_ValueChanged);
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+    }
+
+    #region Event handlers
+    void TardinessPenaltyParameter_ValueChanged(object sender, EventArgs e) {
+      TardinessPenaltyParameter.Value.ValueChanged += new EventHandler(TardinessPenalty_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TardinessPenalty_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void TimeFactorParameter_ValueChanged(object sender, EventArgs e) {
+      TimeFactorParameter.Value.ValueChanged += new EventHandler(TimeFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void TimeFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
   }
 }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 4860)
@@ -77,4 +77,19 @@
     }
 
+    protected OptionalValueParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (OptionalValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    protected OptionalValueParameter<VRPSolution> BestKnownSolutionParameter {
+      get { return (OptionalValueParameter<VRPSolution>)Parameters["BestKnownSolution"]; }
+    }
+
+    IValueParameter<DoubleValue> IVRPProblemInstance.BestKnownQualityParameter {
+      get { return BestKnownQualityParameter; }
+    }
+
+    IValueParameter<VRPSolution> IVRPProblemInstance.BestKnownSolutionParameter {
+      get { return BestKnownSolutionParameter; }
+    }
+
     public DoubleMatrix Coordinates {
       get { return CoordinatesParameter.Value; }
@@ -109,4 +124,13 @@
       get { return DistanceFactorParameter.Value; }
       set { DistanceFactorParameter.Value = value; }
+    }
+
+    public DoubleValue BestKnownQuality {
+      get { return BestKnownQualityParameter.Value; }
+      set { BestKnownQualityParameter.Value = value; }
+    }
+    public VRPSolution BestKnownSolution {
+      get { return BestKnownSolutionParameter.Value; }
+      set { BestKnownSolutionParameter.Value = value; }
     }
 
@@ -171,4 +195,14 @@
     public double Evaluate(Tour tour) {
       return EvaluatorParameter.Value.Evaluate(this, tour).Quality;
+    }
+
+    protected void EvalBestKnownSolution() {
+      if (BestKnownSolution != null) {
+        //call evaluator
+        BestKnownQuality = new DoubleValue(Evaluate(BestKnownSolution.Solution));
+        BestKnownSolution.Quality = BestKnownQuality;
+      } else {
+        BestKnownQuality = null;
+      }
     }
 
@@ -192,9 +226,81 @@
       Parameters.Add(new ValueParameter<IVRPCreator>("SolutionCreator", "The operator which should be used to create new VRP solutions.", Creator));
       Parameters.Add(new ValueParameter<IVRPEvaluator>("Evaluator", "The operator which should be used to evaluate VRP solutions.", Evaluator));
+
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+      Parameters.Add(new OptionalValueParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
+
+      AttachEventHandlers();
     }
 
     protected VRPProblemInstance(VRPProblemInstance original, Cloner cloner)
       : base(original, cloner) {
-    }
+        AttachEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      #region Backwards Compatibility
+      if (!Parameters.ContainsKey("BestKnownSolution")) {
+        Parameters.Add(new OptionalValueParameter<VRPSolution>("BestKnownSolution", "The best known solution of this TSP instance."));
+      }
+      #endregion
+      
+      AttachEventHandlers();
+    }
+
+    private void AttachEventHandlers() {
+      BestKnownSolutionParameter.ValueChanged += new EventHandler(BestKnownSolutionParameter_ValueChanged);
+      DistanceFactorParameter.ValueChanged += new EventHandler(DistanceFactorParameter_ValueChanged);
+      DistanceFactorParameter.Value.ValueChanged += new EventHandler(DistanceFactor_ValueChanged);
+      FleetUsageFactorParameter.ValueChanged += new EventHandler(FleetUsageFactorParameter_ValueChanged);
+      FleetUsageFactorParameter.Value.ValueChanged += new EventHandler(FleetUsageFactor_ValueChanged);
+      DistanceMatrixParameter.ValueChanged += new EventHandler(DistanceMatrixParameter_ValueChanged);
+      if (DistanceMatrix != null) {
+        DistanceMatrix.ItemChanged += new EventHandler<EventArgs<int, int>>(DistanceMatrix_ItemChanged);
+        DistanceMatrix.Reset += new EventHandler(DistanceMatrix_Reset);
+      }
+      UseDistanceMatrixParameter.ValueChanged += new EventHandler(UseDistanceMatrixParameter_ValueChanged);
+      UseDistanceMatrix.ValueChanged += new EventHandler(UseDistanceMatrix_ValueChanged);
+    }
+
+    #region Event handlers
+    void BestKnownSolutionParameter_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void DistanceFactorParameter_ValueChanged(object sender, EventArgs e) {
+      DistanceFactorParameter.Value.ValueChanged += new EventHandler(DistanceFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void DistanceFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void FleetUsageFactorParameter_ValueChanged(object sender, EventArgs e) {
+      FleetUsageFactorParameter.Value.ValueChanged += new EventHandler(FleetUsageFactor_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void FleetUsageFactor_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void DistanceMatrixParameter_ValueChanged(object sender, EventArgs e) {
+      if (DistanceMatrix != null) {
+        DistanceMatrix.ItemChanged += new EventHandler<EventArgs<int, int>>(DistanceMatrix_ItemChanged);
+        DistanceMatrix.Reset += new EventHandler(DistanceMatrix_Reset);
+      }
+      EvalBestKnownSolution();
+    }
+    void DistanceMatrix_Reset(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    void DistanceMatrix_ItemChanged(object sender, EventArgs<int, int> e) {
+      EvalBestKnownSolution();
+    }
+    void UseDistanceMatrixParameter_ValueChanged(object sender, EventArgs e) {
+      UseDistanceMatrix.ValueChanged += new EventHandler(UseDistanceMatrix_ValueChanged);
+      EvalBestKnownSolution();
+    }
+    void UseDistanceMatrix_ValueChanged(object sender, EventArgs e) {
+      EvalBestKnownSolution();
+    }
+    #endregion
   }
 }
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/SolutionParser.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/SolutionParser.cs	(revision 4860)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/SolutionParser.cs	(revision 4860)
@@ -0,0 +1,63 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.IO;
+
+namespace HeuristicLab.Problems.VehicleRouting {
+  class SolutionParser {
+    private string file;
+
+    private List<List<int>> routes;
+
+    public List<List<int>> Routes {
+      get {
+        return routes;
+      }
+    }
+
+    public SolutionParser(string file) {
+      this.file = file;
+      this.routes = new List<List<int>>();
+    }
+
+    public void Parse() {
+      this.routes.Clear();
+      using (StreamReader reader = new StreamReader(file)) {
+        String line;
+        while ((line = reader.ReadLine()) != null) {
+          string[] token = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
+
+          if (token.Length > 2) {
+            List<int> route = new List<int>();
+
+            for (int i = 2; i < token.Length; i++) {
+              route.Add(int.Parse(token[i]));
+            }
+
+            routes.Add(route);
+          }
+        }
+      }
+    }
+  }
+}
Index: /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs
===================================================================
--- /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 4859)
+++ /branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 4860)
@@ -64,4 +64,7 @@
       get { return BestKnownQualityParameter; }
     }
+    public OptionalValueParameter<VRPSolution> BestKnownSolutionParameter {
+      get { return (OptionalValueParameter<VRPSolution>)Parameters["BestKnownSolution"]; }
+    }
     public IValueParameter<IVRPCreator> SolutionCreatorParameter {
       get { return (IValueParameter<IVRPCreator>)Parameters["SolutionCreator"]; }
@@ -82,4 +85,9 @@
       get { return ProblemInstanceParameter.Value; }
       set { ProblemInstanceParameter.Value = value; }
+    }
+
+    public VRPSolution BestKnownSolution {
+      get { return BestKnownSolutionParameter.Value; }
+      set { BestKnownSolutionParameter.Value = value; }
     }
 
@@ -111,4 +119,5 @@
       Parameters.Add(new ValueParameter<IVRPProblemInstance>("ProblemInstance", "The VRP problem instance"));
       Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this VRP instance."));
+      Parameters.Add(new OptionalValueParameter<VRPSolution>("BestKnownSolution", "The best known solution of this VRP instance."));
 
       operators = new List<IOperator>();
@@ -172,4 +181,11 @@
         Parameters.Remove("SolutionCreator");
 
+      if (Parameters.ContainsKey("BestKnownSolution"))
+        Parameters.Remove("BestKnownSolution");
+
+      if (Parameters.ContainsKey("BestKnownQuality"))
+        Parameters.Remove("BestKnownQuality");
+
+
       if (ProblemInstance != null) {
         ProblemInstance.SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
@@ -177,4 +193,7 @@
         Parameters.Add(ProblemInstance.EvaluatorParameter);
         Parameters.Add(ProblemInstance.SolutionCreatorParameter);
+
+        Parameters.Add(ProblemInstance.BestKnownQualityParameter);
+        Parameters.Add(ProblemInstance.BestKnownSolutionParameter);
       }
     }
@@ -251,9 +270,13 @@
       int problemSize = parser.Demands.Length;
 
-      if (parser.Depot != 1)
-        throw new Exception("Invalid depot specification");
-
-      if (parser.WeightType != TSPLIBParser.TSPLIBEdgeWeightType.EUC_2D)
-        throw new Exception("Invalid weight type");
+      if (parser.Depot != 1) {
+        ErrorHandling.ShowErrorDialog(new Exception("Invalid depot specification"));
+        return;
+      }
+
+      if (parser.WeightType != TSPLIBParser.TSPLIBEdgeWeightType.EUC_2D)  {
+        ErrorHandling.ShowErrorDialog(new Exception("Invalid weight type"));
+        return;
+      }
 
       CVRPTWProblemInstance problem = new CVRPTWProblemInstance();
@@ -337,4 +360,27 @@
       this.ProblemInstance = problem;
     }
+
+    public void ImportSolution(string solutionFileName) {
+      SolutionParser parser = new SolutionParser(solutionFileName);
+      parser.Parse();
+
+      HeuristicLab.Problems.VehicleRouting.Encodings.Potvin.PotvinEncoding encoding = new Encodings.Potvin.PotvinEncoding(ProblemInstance);
+
+      int cities = 0;
+      foreach (List<int> route in parser.Routes) {
+        Tour tour = new Tour();
+        tour.Stops.AddRange(route);
+        cities += tour.Stops.Count;
+
+        encoding.Tours.Add(tour);
+      }
+
+      if (cities != ProblemInstance.Coordinates.Rows - 1)
+        ErrorHandling.ShowErrorDialog(new Exception("The optimal solution does not seem to correspond with the problem data"));
+      else {
+        VRPSolution solution = new VRPSolution(ProblemInstance, encoding, new DoubleValue(0));
+        ProblemInstance.BestKnownSolutionParameter.Value = solution;
+      }
+    }
   }
 }
