Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj	(revision 8661)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj	(revision 8663)
@@ -117,4 +117,5 @@
   <ItemGroup>
     <Compile Include="AlgorithmBehaviorHelpers.cs" />
+    <Compile Include="PathRelinkerPerformanceAnalyzer.cs" />
     <Compile Include="VariableRemover.cs" />
     <Compile Include="LinearLeastSquaresFitting.cs" />
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/PathRelinkerPerformanceAnalyzer.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/PathRelinkerPerformanceAnalyzer.cs	(revision 8663)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/PathRelinkerPerformanceAnalyzer.cs	(revision 8663)
@@ -0,0 +1,244 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TravelingSalesman;
+
+namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
+  [Item("PathRelinkerPerformanceAnalyzer", "An operator that analyzes the performance of path relinkers.")]
+  [StorableClass]
+  public class PathRelinkerPerformanceAnalyzer : SingleSuccessorOperator, IAnalyzer {
+    private const string ResultsParameterName = "Results";
+    private const string GenerationsParameterName = "Generations";
+
+    #region IAnalyzer Members
+    public bool EnabledByDefault {
+      get { return true; }
+    }
+    #endregion
+
+    #region Parameter properties
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
+    }
+    public ILookupParameter<IntValue> GenerationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
+    }
+    public ILookupParameter<ItemArray<Permutation>> ParentsParameter {
+      get { return (ScopeTreeLookupParameter<Permutation>)Parameters["Parents"]; }
+    }
+    public ILookupParameter<ItemArray<DoubleValue>> ParentsQualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["ParentsQuality"]; }
+    }
+    public ILookupParameter<ItemArray<Permutation>> ChildParameter {
+      get { return ((ScopeTreeLookupParameter<Permutation>)Parameters["Child"]); }
+    }
+    public IValueParameter<SingleObjectiveSolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueParameter<SingleObjectiveSolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    }
+    public ILookupParameter<TSPRoundedEuclideanPathEvaluator> EvaluatorParameter {
+      get { return (ILookupParameter<TSPRoundedEuclideanPathEvaluator>)Parameters["Evaluator"]; }
+    }
+    private ScopeParameter CurrentScopeParameter {
+      get { return (ScopeParameter)Parameters["CurrentScope"]; }
+    }
+    public IScope CurrentScope {
+      get { return CurrentScopeParameter.ActualValue; }
+    }
+    public ILookupParameter<DoubleMatrix> CoordinatesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Coordinates"]; }
+    }
+    #endregion
+
+    #region Properties
+    public ResultCollection Results {
+      get { return ResultsParameter.ActualValue; }
+    }
+    #endregion
+
+    [Storable]
+    private ScatterPlotHelper plotHelper, childDiversityHelper, parentDiversityHelper;
+    [Storable]
+    private DataTableHelper performanceHelper, successHelper, equalParentsHelper;
+    [Storable]
+    private int cnt = 0;
+    [Storable]
+    private int cntChild = 0;
+    [Storable]
+    private int success = 0;
+    [Storable]
+    private int lastGeneration = 0;
+    [Storable]
+    private int equalParents = 0;
+    [Storable]
+    private List<double> qualityPoints = new List<double>();
+
+    [StorableConstructor]
+    private PathRelinkerPerformanceAnalyzer(bool deserializing) : base(deserializing) { }
+    private PathRelinkerPerformanceAnalyzer(PathRelinkerPerformanceAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+      cnt = original.cnt;
+      cntChild = original.cntChild;
+      success = original.success;
+      lastGeneration = original.lastGeneration;
+      equalParents = original.equalParents;
+      qualityPoints = new List<double>(original.qualityPoints);
+      plotHelper = (ScatterPlotHelper)original.plotHelper.Clone(cloner);
+      childDiversityHelper = (ScatterPlotHelper)original.childDiversityHelper.Clone(cloner);
+      parentDiversityHelper = (ScatterPlotHelper)original.parentDiversityHelper.Clone(cloner);
+      performanceHelper = (DataTableHelper)original.performanceHelper.Clone(cloner);
+      successHelper = (DataTableHelper)original.successHelper.Clone(cloner);
+      equalParentsHelper = (DataTableHelper)original.equalParentsHelper.Clone(cloner);
+    }
+
+    public PathRelinkerPerformanceAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
+      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "Nr of generations."));
+      GenerationsParameter.ActualName = "Iterations";
+
+      Parameters.Add(new ScopeTreeLookupParameter<Permutation>("Parents", "The parent permutations which have been crossed."));
+      ParentsParameter.ActualName = "TSPTour";
+
+      Parameters.Add(new ScopeTreeLookupParameter<Permutation>("Child", "The child permutation resulting from the crossover.", 2));
+      ChildParameter.ActualName = "TSPTour";
+
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("ParentsQuality", "The quality of the parent solutions."));
+      ParentsQualityParameter.ActualName = "TSPTourLength";
+
+      Parameters.Add(new ValueParameter<SingleObjectiveSolutionSimilarityCalculator>("SimilarityCalculator"));
+
+      Parameters.Add(new LookupParameter<TSPRoundedEuclideanPathEvaluator>("Evaluator"));
+
+      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope whose variables and sub-scopes should be removed."));
+
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the cities."));
+
+      plotHelper = new ScatterPlotHelper(false, true);
+      childDiversityHelper = new ScatterPlotHelper(false, true);
+      parentDiversityHelper = new ScatterPlotHelper(false, true);
+      performanceHelper = new DataTableHelper();
+      successHelper = new DataTableHelper();
+      equalParentsHelper = new DataTableHelper();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PathRelinkerPerformanceAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      SimilarityCalculatorParameter.Value.QualityVariableName = "TSPTourLength";
+      SimilarityCalculatorParameter.Value.SolutionVariableName = "TSPTour";
+
+      plotHelper.InitializePlot(Results, "Crossover Performance", "Solution Index", "Absolut Quality Difference");
+      childDiversityHelper.InitializePlot(Results, "Child Diversity", "Solution Index", "Diversity");
+      parentDiversityHelper.InitializePlot(Results, "Parent Diversity", "Solution Index", "Diversity");
+
+      performanceHelper.InitializeChart(Results, "Average Crossover Performance", "Average Crossover Performance per Generation");
+      successHelper.InitializeChart(Results, "Successfull Crossovers", "Successfull Crossovers per Generation");
+      equalParentsHelper.InitializeChart(Results, "Number of equal parents", "Absolut number of equal parents");
+
+      Point2D<double> qualityPoint, diversityPointChild, diversityPointParent;
+
+      var qualityParent1 = ParentsQualityParameter.ActualValue.First().Value;
+      var qualityParent2 = ParentsQualityParameter.ActualValue.Last().Value;
+      var childs = ChildParameter.ActualValue;
+      var parent1 = ParentsParameter.ActualValue.First();
+      var parent2 = ParentsParameter.ActualValue.Last();
+      var parentDiversity = SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope.SubScopes[0], ExecutionContext.Scope.SubScopes[1]);
+      string curGenStr = GenerationsParameter.ActualValue.Value.ToString();
+
+
+      diversityPointParent = new Point2D<double>(cnt++, parentDiversity);
+      List<Point2D<double>> tmpDiversityPointChilds = new List<Point2D<double>>();
+
+      double worseQuality = qualityParent1 > qualityParent2 ? qualityParent1 : qualityParent2;
+      if (qualityParent1 > qualityParent2) {
+        foreach (var child in ExecutionContext.Scope.SubScopes.Last().SubScopes) {
+          diversityPointChild = new Point2D<double>(cntChild++, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(child, ExecutionContext.Scope.SubScopes[0]));
+          tmpDiversityPointChilds.Add(diversityPointChild);
+        }
+      } else {
+        foreach (var child in ExecutionContext.Scope.SubScopes.Last().SubScopes) {
+          diversityPointChild = new Point2D<double>(cntChild++, SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(child, ExecutionContext.Scope.SubScopes[1]));
+          tmpDiversityPointChilds.Add(diversityPointChild);
+        }
+      }
+
+      List<Point2D<double>> tmpQualityPoints = new List<Point2D<double>>();
+      int tmpCnt = cntChild - childs.Length;
+      foreach (var child in childs) {
+        double childQuality = TSPRoundedEuclideanPathEvaluator.Apply(EvaluatorParameter.ActualValue, CoordinatesParameter.ActualValue, child);
+
+        qualityPoint = new Point2D<double>(tmpCnt++, worseQuality - childQuality);
+        tmpQualityPoints.Add(qualityPoint);
+        if ((worseQuality - childQuality) > 0) {
+          success++;
+        }
+        qualityPoints.Add(qualityPoint.Y);
+      }
+
+      if (TSPSimilarityCalculator.CalculateSimilarity(parent1, parent2) == 1.0) {
+        equalParents++;
+      }
+
+      if (GenerationsParameter.ActualValue.Value != 0) {
+        if (GenerationsParameter.ActualValue.Value > lastGeneration) {
+          double avg = qualityPoints.Average();
+
+          performanceHelper.AddPoint(avg);
+          successHelper.AddPoint(success);
+          equalParentsHelper.AddPoint(equalParents);
+
+          Reset();
+        }
+
+        tmpQualityPoints.ForEach(x => plotHelper.AddPoint(curGenStr, x));
+        tmpDiversityPointChilds.ForEach(x => childDiversityHelper.AddPoint(curGenStr, x));
+        parentDiversityHelper.AddPoint(curGenStr, diversityPointParent);
+      } else {
+        Reset();
+      }
+
+      return base.Apply();
+    }
+
+    private void Reset() {
+      cnt = 0;
+      success = 0;
+      lastGeneration = GenerationsParameter.ActualValue.Value;
+      qualityPoints.Clear();
+      equalParents = 0;
+      cntChild = 0;
+    }
+  }
+}
