Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/CrossoverPerformanceAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/CrossoverPerformanceAnalyzer.cs	(revision 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/CrossoverPerformanceAnalyzer.cs	(revision 8797)
@@ -27,5 +27,4 @@
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.PermutationEncoding;
-using HeuristicLab.Operators;
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
@@ -35,7 +34,8 @@
   [Item("CrossoverPerformanceAnalyzer", "An operator that analyzes the performance of crossovers.")]
   [StorableClass]
-  public class CrossoverPerformanceAnalyzer : SingleSuccessorOperator, IAnalyzer {
+  public class CrossoverPerformanceAnalyzer : InitializableOperator, IAnalyzer {
     private const string ResultsParameterName = "Results";
     private const string GenerationsParameterName = "Generations";
+    private const string SuccessfullCrossoversRowName = "Successfull Crossovers per Generation with CompFact ";
 
     #region IAnalyzer Members
@@ -46,4 +46,10 @@
 
     #region Parameter properties
+    public IValueLookupParameter<BoolValue> MaximizationParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public IValueParameter<ItemCollection<DoubleValue>> ComparisonFactorParameter {
+      get { return (IValueParameter<ItemCollection<DoubleValue>>)Parameters["ComparisonFactor"]; }
+    }
     public ILookupParameter<ResultCollection> ResultsParameter {
       get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
@@ -85,5 +91,5 @@
     private int cnt = 0;
     [Storable]
-    private int success = 0;
+    private int[] success;
     [Storable]
     private int lastGeneration = 0;
@@ -98,5 +104,5 @@
       : base(original, cloner) {
       cnt = original.cnt;
-      success = original.success;
+      success = (int[])original.success.Clone();
       lastGeneration = original.lastGeneration;
       equalParents = original.equalParents;
@@ -129,4 +135,10 @@
       Parameters.Add(new ValueParameter<ISingleObjectiveSolutionSimilarityCalculator>("SimilarityCalculator"));
       Parameters.Add(new LookupParameter<ItemCollection<IItem>>("Operators", "The operators and items that the problem provides to the algorithms."));
+      Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, false otherwise"));
+      Parameters.Add(new ValueParameter<ItemCollection<DoubleValue>>("ComparisonFactor", "Determines if the quality should be compared to the better parent (1.0), to the worse (0.0) or to any linearly interpolated value between them."));
+      ComparisonFactorParameter.Value.Add(new DoubleValue(0));
+      ComparisonFactorParameter.Value.Add(new DoubleValue(0.5));
+      ComparisonFactorParameter.Value.Add(new DoubleValue(1));
+
 
       plotHelper = new ScatterPlotHelper(false, true);
@@ -142,7 +154,11 @@
     }
 
-    public override IOperation Apply() {
+    protected override void InitializeAction() {
       if (SimilarityCalculatorParameter.Value == null) {
         SimilarityCalculatorParameter.Value = OperatorsParameter.ActualValue.OfType<ISingleObjectiveSolutionSimilarityCalculator>().FirstOrDefault();
+      }
+
+      if (success == null) {
+        success = new int[ComparisonFactorParameter.Value.Count];
       }
 
@@ -150,12 +166,21 @@
       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");
+      performanceHelper.InitializeChart(Results, "Average Crossover Performance", new string[] { "Average Crossover Performance per Generation" });
+      equalParentsHelper.InitializeChart(Results, "Number of equal parents", new string[] { "Absolut number of equal parents" });
+
+      List<string> successfullCXRowNames = new List<string>();
+      foreach (var value in ComparisonFactorParameter.Value) {
+        successfullCXRowNames.Add(SuccessfullCrossoversRowName + value.Value.ToString());
+      }
+      successHelper.InitializeChart(Results, "Successfull Crossovers", successfullCXRowNames.ToArray());
+    }
+
+    public override IOperation Apply() {
+      Initialize();
 
       Point2D<double> qualityPoint, diversityPointChild, diversityPointParent;
       var qualityParent1 = ParentsQualityParameter.ActualValue.First().Value;
       var qualityParent2 = ParentsQualityParameter.ActualValue.Last().Value;
+      var qualityChild = QualityParameter.ActualValue.Value;
       var child = ChildParameter.ActualValue;
       var parent1 = ParentsParameter.ActualValue.First();
@@ -163,5 +188,4 @@
       var parentDiversity = SimilarityCalculatorParameter.Value.CalculateSolutionSimilarity(ExecutionContext.Scope.SubScopes.First(), ExecutionContext.Scope.SubScopes.Last());
       string curGenStr = GenerationsParameter.ActualValue.Value.ToString();
-
 
       diversityPointParent = new Point2D<double>(cnt, parentDiversity);
@@ -173,9 +197,14 @@
       }
 
-      qualityPoint = new Point2D<double>(cnt++, worseQuality - QualityParameter.ActualValue.Value);
-      if ((worseQuality - QualityParameter.ActualValue.Value) > 0) {
-        success++;
-      }
+      qualityPoint = new Point2D<double>(cnt++, worseQuality - qualityChild);
       qualityPoints.Add(qualityPoint.Y);
+
+      //track successfull cx
+      var compFactsArray = ComparisonFactorParameter.Value.ToArray();
+      for (int i = 0; i < compFactsArray.Length; i++) {
+        if (WeightedParentsQualityComparer.Compare(qualityChild, qualityParent1, qualityParent2, compFactsArray[i].Value, MaximizationParameter.ActualValue.Value)) {
+          success[i]++;
+        }
+      }
 
       if (parentDiversity == 1.0) {
@@ -188,6 +217,9 @@
 
           performanceHelper.AddPoint(avg);
-          successHelper.AddPoint(success);
           equalParentsHelper.AddPoint(equalParents);
+
+          for (int i = 0; i < compFactsArray.Length; i++) {
+            successHelper.AddPoint(SuccessfullCrossoversRowName + compFactsArray[i].Value.ToString(), success[i]);
+          }
 
           Reset();
@@ -206,5 +238,5 @@
     private void Reset() {
       cnt = 0;
-      success = 0;
+      success = new int[ComparisonFactorParameter.Value.Count];
       lastGeneration = GenerationsParameter.ActualValue.Value;
       qualityPoints.Clear();
Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DataTableHelper.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DataTableHelper.cs	(revision 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DataTableHelper.cs	(revision 8797)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Collections.Generic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -35,7 +36,7 @@
     private string chartName;
     [Storable]
-    private string dataRowName;
+    private string[] dataRowNames;
     [Storable]
-    private DataRow dtRow;
+    DataTable dt;
 
     [StorableConstructor]
@@ -49,19 +50,28 @@
     }
 
-    public void InitializeChart(ResultCollection results, string chartName, string dataRowName) {
+    public void InitializeChart(ResultCollection results, string chartName, string[] dataRowNames) {
       if (!results.ContainsKey(chartName)) {
         this.resultsCol = results;
         this.chartName = chartName;
-        this.dataRowName = dataRowName;
+        this.dataRowNames = dataRowNames;
 
-        DataTable dt = new DataTable(chartName);
-        dtRow = new DataRow(dataRowName);
-        dt.Rows.Add(dtRow);
+        dt = new DataTable(chartName);
+
+        foreach (string dataRowName in dataRowNames) {
+          DataRow dtRow = new DataRow(dataRowName);
+          dt.Rows.Add(dtRow);
+        }
+
         results.Add(new Result(chartName, dt));
       }
     }
 
+    public void AddPoint(string dataRow, double point) {
+      dt.Rows[dataRow].Values.Add(point);
+    }
+
     public void AddPoint(double point) {
-      dtRow.Values.Add(point);
+      // assume that there is only 1 row and therefore the name doesn't have to be provided
+      dt.Rows[dataRowNames[0]].Values.Add(point);
     }
   }
Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DuplicateSolutionsAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DuplicateSolutionsAnalyzer.cs	(revision 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DuplicateSolutionsAnalyzer.cs	(revision 8797)
@@ -87,5 +87,5 @@
         SimilarityCalculatorParameter.Value = OperatorsParameter.ActualValue.OfType<ISingleObjectiveSolutionSimilarityCalculator>().FirstOrDefault();
       }
-      chartingHelper.InitializeChart(Results, "Duplicate Solutions", "Duplicate Solutions per Generation");
+      chartingHelper.InitializeChart(Results, "Duplicate Solutions", new string[] { "Duplicate Solutions per Generation" });
 
       var similarities = SimilarityCalculatorParameter.Value.CalculateSolutionCrowdSimilarity(ExecutionContext.Scope);
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 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj	(revision 8797)
@@ -120,4 +120,5 @@
     <Compile Include="AfterCrossoverCombinedOperator.cs" />
     <Compile Include="AfterMutationCombinedOperator.cs" />
+    <Compile Include="InitializableOperator.cs" />
     <Compile Include="PathRelinkerPerformanceAnalyzer.cs" />
     <Compile Include="VariableRemover.cs" />
@@ -137,4 +138,5 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="VariableDuplicator.cs" />
+    <Compile Include="WeightedParentsQualityComparer.cs" />
   </ItemGroup>
   <ItemGroup>
Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/InitializableOperator.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/InitializableOperator.cs	(revision 8797)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/InitializableOperator.cs	(revision 8797)
@@ -0,0 +1,71 @@
+﻿#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;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
+  [Item("InitializableOperator", "An operator that can be initialized on it's first execution.")]
+  [StorableClass]
+  public class InitializableOperator : SingleSuccessorOperator {
+
+    [Storable]
+    private Guid guid;
+
+    public ILookupParameter<BoolValue> Initialized {
+      get { return (ILookupParameter<BoolValue>)Parameters[guid.ToString()]; }
+    }
+
+    [StorableConstructor]
+    protected InitializableOperator(bool deserializing) : base(deserializing) { }
+    protected InitializableOperator(InitializableOperator original, Cloner cloner)
+      : base(original, cloner) {
+      guid = original.guid;
+    }
+    public InitializableOperator()
+      : base() {
+      guid = Guid.NewGuid();
+      Parameters.Add(new LookupParameter<BoolValue>(guid.ToString(), "Indicates if the operator is initialized."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InitializableOperator(this, cloner);
+    }
+
+    protected void Initialize() {
+      if (Initialized.ActualValue == null) {
+        Initialized.ActualValue = new BoolValue(true);
+        InitializeAction();
+      } else if (!Initialized.ActualValue.Value) {
+        Initialized.ActualValue.Value = true;
+        InitializeAction();
+      }
+    }
+
+    protected virtual void InitializeAction() { }
+  }
+}
Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/MutationPerformanceAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/MutationPerformanceAnalyzer.cs	(revision 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/MutationPerformanceAnalyzer.cs	(revision 8797)
@@ -31,5 +31,4 @@
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.TravelingSalesman;
 
 namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
@@ -145,5 +144,5 @@
         qualityPlotHelper.InitializePlot(Results, "Mutation Quality", "Solution Index", "Absolut Quality Difference");
         diversityPlotHelper.InitializePlot(Results, "Mutation Diversity", "Solution Index", "Diversity");
-        avgDataTableHelper.InitializeChart(Results, "Average Mutation Performance", "Average Mutation Performance per Generation");
+        avgDataTableHelper.InitializeChart(Results, "Average Mutation Performance", new string[] { "Average Mutation Performance per Generation" });
 
         Scope permutationBeforeScope = new Scope();
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 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/PathRelinkerPerformanceAnalyzer.cs	(revision 8797)
@@ -164,7 +164,7 @@
       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");
+      performanceHelper.InitializeChart(Results, "Average Crossover Performance", new string[] { "Average Crossover Performance per Generation" });
+      successHelper.InitializeChart(Results, "Successfull Crossovers", new string[] { "Successfull Crossovers per Generation" });
+      equalParentsHelper.InitializeChart(Results, "Number of equal parents", new string[] { "Absolut number of equal parents" });
 
       Point2D<double> qualityPoint, diversityPointChild, diversityPointParent;
Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/ScatterPlotHelper.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/ScatterPlotHelper.cs	(revision 8796)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/ScatterPlotHelper.cs	(revision 8797)
@@ -85,5 +85,5 @@
           dataTableHelper = new DataTableHelper();
         }
-        dataTableHelper.InitializeChart(results, chartName + " Chart", yAxisTitle);
+        dataTableHelper.InitializeChart(results, chartName + " Chart", new string[] { yAxisTitle });
       }
 
Index: /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/WeightedParentsQualityComparer.cs
===================================================================
--- /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/WeightedParentsQualityComparer.cs	(revision 8797)
+++ /branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/WeightedParentsQualityComparer.cs	(revision 8797)
@@ -0,0 +1,82 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
+  /// <summary>
+  /// Compares the quality against that of its parents.
+  /// This is more or less the same code as in the WeightedParentsQualityComparator operator, but without the operator part
+  /// </summary>
+  public static class WeightedParentsQualityComparer {
+    public static bool Compare(double leftQuality, double rightQuality1, double rightQuality2, double compFact, bool maximization) {
+      return Compare(leftQuality, new double[] { rightQuality1, rightQuality2 }, compFact, maximization);
+    }
+
+    public static bool Compare(double leftQuality, IList<double> rightQualities, double compFact, bool maximization) {
+      if (rightQualities.Count < 1) throw new InvalidOperationException("No rightQualities found. ");
+
+      double threshold = 0;
+
+      if (rightQualities.Count == 2) { // this case will probably be used most often
+        double minQuality = Math.Min(rightQualities[0], rightQualities[1]);
+        double maxQuality = Math.Max(rightQualities[0], rightQualities[1]);
+        if (maximization)
+          threshold = minQuality + (maxQuality - minQuality) * compFact;
+        else
+          threshold = maxQuality - (maxQuality - minQuality) * compFact;
+      } else if (rightQualities.Count == 1) { // case for just one parent
+        threshold = rightQualities[0];
+      } else { // general case extended to 3 or more parents
+        List<double> sortedQualities = rightQualities.ToList();
+        sortedQualities.Sort();
+        double minimumQuality = sortedQualities.First();
+
+        double integral = 0;
+        for (int i = 0; i < sortedQualities.Count - 1; i++) {
+          integral += (sortedQualities[i] + sortedQualities[i + 1]) / 2.0; // sum of the trapezoid
+        }
+        integral -= minimumQuality * sortedQualities.Count;
+        if (integral == 0) threshold = sortedQualities[0]; // all qualities are equal
+        else {
+          double selectedArea = integral * (maximization ? compFact : (1 - compFact));
+          integral = 0;
+          for (int i = 0; i < sortedQualities.Count - 1; i++) {
+            double currentSliceArea = (sortedQualities[i] + sortedQualities[i + 1]) / 2.0;
+            double windowedSliceArea = currentSliceArea - minimumQuality;
+            if (windowedSliceArea == 0) continue;
+            integral += windowedSliceArea;
+            if (integral >= selectedArea) {
+              double factor = 1 - ((integral - selectedArea) / (windowedSliceArea));
+              threshold = sortedQualities[i] + (sortedQualities[i + 1] - sortedQualities[i]) * factor;
+              break;
+            }
+          }
+        }
+      }
+
+      bool result = maximization && leftQuality > threshold || !maximization && leftQuality < threshold;
+      return result;
+    }
+  }
+}
