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 4752)
+++ 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 4752)
+++ 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 4752)
+++ 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
   }
 }
