Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisFragmentLengthAnalyzer.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisFragmentLengthAnalyzer.cs	(revision 13625)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Tracking/Analyzers/SymbolicDataAnalysisFragmentLengthAnalyzer.cs	(revision 13747)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Analysis;
@@ -28,4 +29,5 @@
 using HeuristicLab.EvolutionTracking;
 using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -34,4 +36,15 @@
   [StorableClass]
   public class SymbolicDataAnalysisFragmentLengthAnalyzer : EvolutionTrackingAnalyzer<ISymbolicExpressionTree> {
+    private const string StoreHistoryParameterName = "StoryHistory";
+
+    public IFixedValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[StoreHistoryParameterName]; }
+    }
+
+    public bool StoreHistory {
+      get { return StoreHistoryParameter.Value.Value; }
+      set { StoreHistoryParameter.Value.Value = value; }
+    }
+
     [StorableConstructor]
     protected SymbolicDataAnalysisFragmentLengthAnalyzer(bool deserializing) : base(deserializing) { }
@@ -39,4 +52,6 @@
     public SymbolicDataAnalysisFragmentLengthAnalyzer() {
       UpdateCounterParameter.ActualName = "FragmentLengthAnalyzerUpdateCounter";
+
+      Parameters.Add(new FixedValueParameter<BoolValue>(StoreHistoryParameterName, new BoolValue(false)));
     }
 
@@ -65,10 +80,9 @@
 
       // consider all fragments (including those of the intermediate crossover children)
-      double averageCrossoverFragmentLength = 0;
-      double averageMutationFragmentLength = 0;
-      int crossoverChildren = 0;
-      int mutationChildren = 0;
-
       var vertices = PopulationGraph.Vertices.Where(x => x.Rank > Generation.Value - 1);
+      var crossoverFragmentLengthDistribution = new List<double>();
+      var replacedCrossoverFragmentLengthDistribution = new List<double>();
+      var mutationFragmentLengthDistribution = new List<double>();
+      var replacedMutationFragmentLengthDistribution = new List<double>();
       foreach (var v in vertices) {
         if (!v.InArcs.Any() || v.InArcs.Last().Data == null)
@@ -76,15 +90,26 @@
         var fragment = (IFragment<ISymbolicExpressionTreeNode>)v.InArcs.Last().Data;
         if (v.InDegree == 2) {
-          averageCrossoverFragmentLength += fragment.Root.GetLength();
-          crossoverChildren++;
+          crossoverFragmentLengthDistribution.Add(fragment.Root.GetLength());
+          int index = 0;
+          foreach (var s in v.Parents.First().Data.IterateNodesPrefix()) {
+            if (index == fragment.Index1) {
+              replacedCrossoverFragmentLengthDistribution.Add(s.GetLength());
+              break;
+            }
+            index++;
+          }
         } else {
-          averageMutationFragmentLength += fragment.Root.GetLength();
-          mutationChildren++;
+          mutationFragmentLengthDistribution.Add(fragment.Root.GetLength());
+          int index = 0;
+          foreach (var s in v.Parents.First().Data.IterateNodesPrefix()) {
+            if (index == fragment.Index1) {
+              replacedMutationFragmentLengthDistribution.Add(s.GetLength());
+              break;
+            }
+            index++;
+          }
         }
       }
-      var averageFragmentLength = (averageCrossoverFragmentLength + averageMutationFragmentLength) / (crossoverChildren + mutationChildren);
-      averageCrossoverFragmentLength /= crossoverChildren;
-      averageMutationFragmentLength /= mutationChildren;
-
+      var averageFragmentLength = (crossoverFragmentLengthDistribution.Average() + mutationFragmentLengthDistribution.Average()) / 2d;
       DataTable table;
       if (!Results.ContainsKey("AverageFragmentLength")) {
@@ -94,8 +119,14 @@
         table.Rows.Add(row);
         row = new DataRow("Average crossover fragment length") { VisualProperties = { StartIndexZero = true } };
-        row.Values.Add(averageCrossoverFragmentLength);
+        row.Values.Add(crossoverFragmentLengthDistribution.Average());
+        table.Rows.Add(row);
+        row = new DataRow("Average replaced crossover fragment length") { VisualProperties = { StartIndexZero = true } };
+        row.Values.Add(replacedCrossoverFragmentLengthDistribution.Average());
         table.Rows.Add(row);
         row = new DataRow("Average mutation fragment length") { VisualProperties = { StartIndexZero = true } };
-        row.Values.Add(averageMutationFragmentLength);
+        row.Values.Add(mutationFragmentLengthDistribution.Average());
+        table.Rows.Add(row);
+        row = new DataRow("Average replaced mutation fragment length") { VisualProperties = { StartIndexZero = true } };
+        row.Values.Add(replacedMutationFragmentLengthDistribution.Average());
         table.Rows.Add(row);
         Results.Add(new Result("AverageFragmentLength", table));
@@ -103,6 +134,40 @@
         table = (DataTable)Results["AverageFragmentLength"].Value;
         table.Rows["Average fragment length"].Values.Add(averageFragmentLength);
-        table.Rows["Average crossover fragment length"].Values.Add(averageCrossoverFragmentLength);
-        table.Rows["Average mutation fragment length"].Values.Add(averageMutationFragmentLength);
+        table.Rows["Average crossover fragment length"].Values.Add(crossoverFragmentLengthDistribution.Average());
+        table.Rows["Average replaced crossover fragment length"].Values.Add(replacedCrossoverFragmentLengthDistribution.Average());
+        table.Rows["Average mutation fragment length"].Values.Add(mutationFragmentLengthDistribution.Average());
+        table.Rows["Average replaced mutation fragment length"].Values.Add(replacedMutationFragmentLengthDistribution.Average());
+      }
+      if (!Results.ContainsKey("FragmentLengthDistribution")) {
+        table = new DataTable("Table length distribution");
+        var row = new DataRow("Crossover fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } };
+        row.Values.Replace(crossoverFragmentLengthDistribution);
+        table.Rows.Add(row);
+        row = new DataRow("Replaced crossover fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } };
+        row.Values.Replace(replacedCrossoverFragmentLengthDistribution);
+        table.Rows.Add(row);
+        row = new DataRow("Mutation fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } };
+        row.Values.Replace(mutationFragmentLengthDistribution);
+        table.Rows.Add(row);
+        row = new DataRow("Replaced mutation fragment length distribution") { VisualProperties = { StartIndexZero = true, ChartType = DataRowVisualProperties.DataRowChartType.Histogram } };
+        row.Values.Replace(replacedMutationFragmentLengthDistribution);
+        table.Rows.Add(row);
+        Results.Add(new Result("FragmentLengthDistribution", table));
+      } else {
+        table = (DataTable)Results["FragmentLengthDistribution"].Value;
+        table.Rows["Crossover fragment length distribution"].Values.Replace(crossoverFragmentLengthDistribution);
+        table.Rows["Mutation fragment length distribution"].Values.Replace(mutationFragmentLengthDistribution);
+        table.Rows["Replaced crossover fragment length distribution"].Values.Replace(replacedCrossoverFragmentLengthDistribution);
+        table.Rows["Replaced mutation fragment length distribution"].Values.Replace(replacedMutationFragmentLengthDistribution);
+      }
+      if (StoreHistory) {
+        if (!Results.ContainsKey("FragmentLengthDistributionHistory")) {
+          var history = new DataTableHistory();
+          history.Add(table);
+          Results.Add(new Result("FragmentLengthDistributionHistory", history));
+        } else {
+          var history = (DataTableHistory)Results["FragmentLengthDistributionHistory"].Value;
+          history.Add(table);
+        }
       }
       return base.Apply();
