Index: /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering.Views/3.3/OrienteeringProblemView.cs
===================================================================
--- /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering.Views/3.3/OrienteeringProblemView.cs	(revision 11310)
+++ /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering.Views/3.3/OrienteeringProblemView.cs	(revision 11311)
@@ -63,5 +63,5 @@
       } else {
         orienteeringSolutionView.Content = new OrienteeringSolution(
-          Content.BestKnownSolution, Content.Coordinates, Content.StartingPoint, Content.TerminusPoint, Content.Scores, Content.BestKnownQuality);
+          Content.BestKnownSolution, Content.Coordinates, Content.StartingPoint, Content.TerminusPoint, Content.Scores, Content.BestKnownQuality, penalty: null);
       }
     }
Index: /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering.Views/3.3/OrienteeringSolutionView.cs
===================================================================
--- /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering.Views/3.3/OrienteeringSolutionView.cs	(revision 11310)
+++ /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering.Views/3.3/OrienteeringSolutionView.cs	(revision 11311)
@@ -42,4 +42,5 @@
     protected override void DeregisterContentEvents() {
       Content.QualityChanged -= new EventHandler(Content_QualityChanged);
+      Content.PenaltyChanged -= new EventHandler(Content_PenaltyChanged);
       Content.CoordinatesChanged -= new EventHandler(Content_CoordinatesChanged);
       Content.StartingPointChanged -= new EventHandler(Content_StartingPointChanged);
@@ -52,4 +53,5 @@
       base.RegisterContentEvents();
       Content.QualityChanged += new EventHandler(Content_QualityChanged);
+      Content.PenaltyChanged += new EventHandler(Content_PenaltyChanged);
       Content.CoordinatesChanged += new EventHandler(Content_CoordinatesChanged);
       Content.StartingPointChanged += new EventHandler(Content_StartingPointChanged);
@@ -114,5 +116,6 @@
                   tour[i] = points[integerVector[i]];
                 }
-                graphics.DrawLines(Pens.Black, tour);
+                bool visualizePenalty = Content.Penalty != null && Content.Penalty.Value > 0;
+                graphics.DrawLines(visualizePenalty ? Pens.Red : Pens.Black, tour);
               }
 
@@ -154,4 +157,10 @@
         qualityViewHost.Content = Content.Quality;
     }
+    private void Content_PenaltyChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_PenaltyChanged), sender, e);
+      else
+        GenerateImage();
+    }
     private void Content_CoordinatesChanged(object sender, EventArgs e) {
       if (InvokeRequired)
Index: /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/Analyzers/BestOrienteeringSolutionAnalyser.cs
===================================================================
--- /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/Analyzers/BestOrienteeringSolutionAnalyser.cs	(revision 11310)
+++ /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/Analyzers/BestOrienteeringSolutionAnalyser.cs	(revision 11311)
@@ -55,4 +55,7 @@
       get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
     }
+    public ScopeTreeLookupParameter<DoubleValue> PenaltyParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Penalty"]; }
+    }
     public LookupParameter<OrienteeringSolution> BestSolutionParameter {
       get { return (LookupParameter<OrienteeringSolution>)Parameters["BestSolution"]; }
@@ -66,4 +69,7 @@
     public LookupParameter<IntegerVector> BestKnownSolutionParameter {
       get { return (LookupParameter<IntegerVector>)Parameters["BestKnownSolution"]; }
+    }
+    public LookupParameter<DoubleValue> BestKnownSolutionPenaltyParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["BestKnownSolutionPenalty"]; }
     }
 
@@ -82,8 +88,10 @@
       Parameters.Add(new LookupParameter<DoubleArray>("Scores", "The scores of the points."));
       Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the Orienteering solutions which should be analyzed."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Penalty", "The applied penalty of the Orienteering solutions."));
       Parameters.Add(new LookupParameter<OrienteeringSolution>("BestSolution", "The best Orienteering solution."));
       Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the best Orienteering solution should be stored."));
       Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this Orienteering instance."));
       Parameters.Add(new LookupParameter<IntegerVector>("BestKnownSolution", "The best known solution of this Orienteering instance."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownSolutionPenalty", "The penalty of the best known solution of this Orienteering instance."));
     }
 
@@ -91,4 +99,5 @@
       var solutions = IntegerVector.ActualValue;
       var qualities = QualityParameter.ActualValue;
+      var penalties = PenaltyParameter.ActualValue;
       var results = ResultsParameter.ActualValue;
       var bestKnownQuality = BestKnownQualityParameter.ActualValue;
@@ -99,4 +108,5 @@
         BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[bestIndex].Value);
         BestKnownSolutionParameter.ActualValue = (IntegerVector)solutions[bestIndex].Clone();
+        BestKnownSolutionPenaltyParameter.ActualValue = new DoubleValue(penalties[bestIndex].Value);
       }
 
@@ -113,7 +123,9 @@
           terminusPoint,
           scores,
-          new DoubleValue(qualities[bestIndex].Value));
+          new DoubleValue(qualities[bestIndex].Value),
+          new DoubleValue(penalties[bestIndex].Value));
         BestSolutionParameter.ActualValue = solution;
         results.Add(new Result("Best Orienteering Solution", solution));
+        results.Add(new Result("BestKnownSolutionPenalty", solution.Penalty));
       } else {
         if (solution.Quality.Value < qualities[bestIndex].Value) {
@@ -122,4 +134,6 @@
           solution.IntegerVector = (IntegerVector)solutions[bestIndex].Clone();
           solution.Quality.Value = qualities[bestIndex].Value;
+          solution.Penalty.Value = penalties[bestIndex].Value;
+          results["BestKnownSolutionPenalty"].Value = solution.Penalty;
         }
       }
Index: /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/Evaluators/OrienteeringEvaluator.cs
===================================================================
--- /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/Evaluators/OrienteeringEvaluator.cs	(revision 11310)
+++ /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/Evaluators/OrienteeringEvaluator.cs	(revision 11311)
@@ -20,4 +20,6 @@
 #endregion
 
+using System.Linq;
+using System.Security.Permissions;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -30,6 +32,14 @@
 namespace HeuristicLab.Problems.Orienteering {
   public class OrienteeringEvaluator : InstrumentedOperator, IOrienteeringEvaluator {
+
+    #region ParameterProperties
     public ILookupParameter<DoubleValue> QualityParameter {
       get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> PenaltyParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Penalty"]; }
+    }
+    public ILookupParameter<DoubleValue> DistancePenaltyFactorParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["DistancePenaltyFactor"]; }
     }
     public ILookupParameter<IntegerVector> IntegerVectorParameter {
@@ -39,4 +49,14 @@
       get { return (ILookupParameter<DoubleArray>)Parameters["Scores"]; }
     }
+    public ILookupParameter<DistanceMatrix> DistanceMatrixParameter {
+      get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; }
+    }
+    public ILookupParameter<DoubleValue> MaximumDistanceParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MaximumDistance"]; }
+    }
+    public ILookupParameter<DoubleValue> FixedPenaltyParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["FixedPenalty"]; }
+    }
+    #endregion
 
     [StorableConstructor]
@@ -53,29 +73,45 @@
       : base() {
       Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The evaluated quality of the Orienteering solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Penalty", "The applied penalty"));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("DistancePenaltyFactor", "The penalty applied per distance violation.", new DoubleValue(0)));
+
       Parameters.Add(new LookupParameter<IntegerVector>("IntegerVector", "The Orienteering Solution given in path representation."));
       Parameters.Add(new LookupParameter<DoubleArray>("Scores", "The scores of the points."));
+      Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the points."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MaximumDistance", "The maximum distance constraint for a Orienteering solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("FixedPenalty", "The penalty for each visited vertex."));
     }
 
     public class OrienteeringEvaluation {
       public DoubleValue Quality;
+      public DoubleValue Penalty;
     }
 
-    public static OrienteeringEvaluation Apply(IntegerVector solution, DoubleArray scores) {
-      // TODO distance penalty
-      double score = 0.0;
+    public static OrienteeringEvaluation Apply(IntegerVector solution, DoubleArray scores,
+      DistanceMatrix distances, DoubleValue maximumDistance, DoubleValue fixedPenalty, DoubleValue distancePenaltyFactor) {
 
-      for (int i = 0; i < solution.Length; i++) {
-        score += scores[solution[i]];
-      }
+      double score = solution.Sum(t => scores[t]);
+      double distance = distances.CalculateTourLength(solution.ToList(), fixedPenalty.Value);
+
+      double distanceViolation = distance - maximumDistance.Value;
+
+      double penalty = 0.0;
+      penalty += distanceViolation > 0 ? distanceViolation * distancePenaltyFactor.Value : 0;
+
+      double quality = score - penalty;
 
       return new OrienteeringEvaluation {
-        Quality = new DoubleValue(score)
+        Quality = new DoubleValue(quality),
+        Penalty = new DoubleValue(penalty)
       };
     }
 
     public override IOperation InstrumentedApply() {
-      var evaluation = Apply(IntegerVectorParameter.ActualValue, ScoresParameter.ActualValue);
+      var evaluation = Apply(IntegerVectorParameter.ActualValue, ScoresParameter.ActualValue,
+        DistanceMatrixParameter.ActualValue, MaximumDistanceParameter.ActualValue,
+        FixedPenaltyParameter.ActualValue, DistancePenaltyFactorParameter.ActualValue);
 
       QualityParameter.ActualValue = evaluation.Quality;
+      PenaltyParameter.ActualValue = evaluation.Penalty;
 
       return base.InstrumentedApply();
Index: /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/OrienteeringSolution.cs
===================================================================
--- /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/OrienteeringSolution.cs	(revision 11310)
+++ /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Problems.Orienteering/3.3/OrienteeringSolution.cs	(revision 11311)
@@ -90,4 +90,17 @@
           if (quality != null) RegisterQualityEvents();
           OnQualityChanged();
+        }
+      }
+    }
+    [Storable]
+    private DoubleValue penalty;
+    public DoubleValue Penalty {
+      get { return penalty; }
+      set {
+        if (penalty != value) {
+          if (penalty != null) DeregisterPenaltyEvents();
+          penalty = value;
+          if (penalty != null) RegisterPenaltyEvents();
+          OnPenaltyChanged();
         }
       }
@@ -102,8 +115,9 @@
       this.coordinates = cloner.Clone(original.coordinates);
       this.quality = cloner.Clone(original.quality);
+      this.penalty = cloner.Clone(original.penalty);
       Initialize();
     }
     public OrienteeringSolution(IntegerVector integerVector, DoubleMatrix coordinates, IntValue startingPoint, IntValue terminusPoint,
-      DoubleArray scores, DoubleValue quality)
+      DoubleArray scores, DoubleValue quality, DoubleValue penalty)
       : base() {
       this.integerVector = integerVector;
@@ -113,4 +127,5 @@
       this.scores = scores;
       this.quality = quality;
+      this.penalty = penalty;
       Initialize();
     }
@@ -132,4 +147,5 @@
       if (scores != null) RegisterScoresEvents();
       if (quality != null) RegisterQualityEvents();
+      if (penalty != null) RegisterPenaltyEvents();
     }
 
@@ -177,4 +193,11 @@
     }
 
+    public event EventHandler PenaltyChanged;
+    private void OnPenaltyChanged() {
+      var changed = PenaltyChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
     private void RegisterIntegerVectorEvents() {
       IntegerVector.ItemChanged += new EventHandler<EventArgs<int>>(IntegerVector_ItemChanged);
@@ -219,4 +242,10 @@
       Quality.ValueChanged -= new EventHandler(Quality_ValueChanged);
     }
+    private void RegisterPenaltyEvents() {
+      Penalty.ValueChanged += new EventHandler(Penalty_ValueChanged);
+    }
+    private void DeregisterPenaltyEvents() {
+      Penalty.ValueChanged -= new EventHandler(Penalty_ValueChanged);
+    }
 
     private void IntegerVector_ItemChanged(object sender, EventArgs<int> e) {
@@ -246,4 +275,7 @@
     private void Quality_ValueChanged(object sender, EventArgs e) {
       OnQualityChanged();
+    }
+    private void Penalty_ValueChanged(object sender, EventArgs e) {
+      OnPenaltyChanged();
     }
     #endregion
