Index: branches/DataAnalysis.PopulationDiversityAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj
===================================================================
--- branches/DataAnalysis.PopulationDiversityAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj	(revision 4885)
+++ branches/DataAnalysis.PopulationDiversityAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj	(revision 4886)
@@ -182,4 +182,5 @@
     <Compile Include="SupportVectorRegression\SupportVectorRegressionSolution.cs" />
     <Compile Include="Symbolic\Analyzers\BestSymbolicRegressionSolutionAnalyzer.cs" />
+    <Compile Include="Symbolic\Analyzers\FineGrainedStructuralPopulationDiversityAnalyzer.cs" />
     <Compile Include="Symbolic\Analyzers\SymbolicRegressionPopulationDiversityAnalyzer.cs" />
     <Compile Include="Symbolic\Analyzers\VariablesUsagePopulationDiversityAnalyzer.cs" />
Index: branches/DataAnalysis.PopulationDiversityAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/FineGrainedStructuralPopulationDiversityAnalyzer.cs
===================================================================
--- branches/DataAnalysis.PopulationDiversityAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/FineGrainedStructuralPopulationDiversityAnalyzer.cs	(revision 4886)
+++ branches/DataAnalysis.PopulationDiversityAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/FineGrainedStructuralPopulationDiversityAnalyzer.cs	(revision 4886)
@@ -0,0 +1,438 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using System.Collections.Generic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Symbols;
+
+namespace HeuristicLab.Problems.DataAnalysis.Regression.Symbolic.Analyzers {
+  /// <summary>
+  /// An operator that analyzes the population diversity using fine grained structural tree similarity estimation.
+  /// </summary>
+  [Item("FineGrainedStructuralPopulationDiversityAnalyzer", "An operator that analyzes the population diversity using fine grained structural tree similarity estimation.")]
+  [StorableClass]
+  public sealed class FineGrainedStructuralPopulationDiversityAnalyzer : SymbolicRegressionPopulationDiversityAnalyzer {
+
+    [StorableConstructor]
+    private FineGrainedStructuralPopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    private FineGrainedStructuralPopulationDiversityAnalyzer(FineGrainedStructuralPopulationDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public FineGrainedStructuralPopulationDiversityAnalyzer() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FineGrainedStructuralPopulationDiversityAnalyzer(this, cloner);
+    }
+
+    protected override double[,] CalculateSimilarities(SymbolicExpressionTree[] solutions) {
+      int n = solutions.Length;
+      double[,] result = new double[n, n];
+      for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+          if (i == j)
+            result[i, j] = 1;
+          else
+            result[i, j] = 0;
+        }
+      }
+      return result;
+    }
+
+    /*
+    #region private class GeneticInformationItem, ported from HL 2
+
+    private class GeneticInformationItem {
+
+      private Type myAncestorDefinition;
+      public Type AncestorDefinition {
+        get { return myAncestorDefinition; }
+      }
+
+      private int myAncestorIndex;
+      public int AncestorIndex {
+        get { return myAncestorIndex; }
+      }
+
+      private Type myDescendantDefinition;
+      public Type DescendantDefinition {
+        get { return myDescendantDefinition; }
+      }
+
+      private int myLevelDelta;
+      public int LevelDelta {
+        get { return myLevelDelta; }
+      }
+
+      private double myAncestorCoefficient;
+      public double AncestorCoefficient {
+        get { return myAncestorCoefficient; }
+      }
+
+      private double myAncestorVariableIndex;
+      public double AncestorVariableIndex {
+        get { return myAncestorVariableIndex; }
+      }
+
+      private int myAncestorTimeOffset;
+      public int AncestorTimeOffset {
+        get { return myAncestorTimeOffset; }
+      }
+
+      // not used in HL 3.3
+      // private int myAncestorVariant;
+      // public int AncestorVariant {
+      //   get { return myAncestorVariant; }
+      // }
+
+      private double myDescendantCoefficient;
+      public double DescendantCoefficient {
+        get { return myDescendantCoefficient; }
+      }
+
+      private double myDescendantVariableIndex;
+      public double DescendantVariableIndex {
+        get { return myDescendantVariableIndex; }
+      }
+
+      private int myDescendantTimeOffset;
+      public int DescendantTimeOffset {
+        get { return myDescendantTimeOffset; }
+      }
+
+      private int myDescendantVariant;
+      public int DescendantVariant {
+        get { return myDescendantVariant; }
+      }
+
+      public GeneticInformationItem(SymbolicExpressionTreeNode Ancestor, SymbolicExpressionTreeNode Descendant) {
+
+        myAncestorDefinition = Ancestor.Symbol.GetType();
+        myAncestorCoefficient = Ancestor.Coefficient;
+        myAncestorTimeOffset = Ancestor.TimeOffset;
+        myAncestorVariableIndex = Ancestor.VariableIndex;
+        //myAncestorVariant = Ancestor.Variant;
+
+        myDescendantDefinition = Descendant.Symbol.GetType();
+        myDescendantCoefficient = Descendant.Coefficient;
+        myDescendantTimeOffset = Descendant.TimeOffset;
+        myDescendantVariableIndex = Descendant.VariableIndex;
+        //myDescendantVariant = Descendant.Variant;
+
+        myLevelDelta = Descendant.Level - Ancestor.Level;
+        if (myLevelDelta < 0)
+          throw new InvalidOperationException("ERROR in GeneticInformationItem: The Given ancestor is not an ancestor of the given descendant node.");
+        myAncestorIndex = CalculateAncestorIndex(Ancestor, Descendant);
+
+      }
+
+      private GeneticInformationItem(GeneticInformationItem item) {
+        myAncestorDefinition = item.myAncestorDefinition;
+        myAncestorCoefficient = item.myAncestorCoefficient;
+        myAncestorTimeOffset = item.myAncestorTimeOffset;
+        myAncestorVariableIndex = item.myAncestorVariableIndex;
+        // myAncestorVariant = item.myAncestorVariant;
+        myDescendantDefinition = item.myDescendantDefinition;
+        myDescendantCoefficient = item.myDescendantCoefficient;
+        myDescendantTimeOffset = item.myDescendantTimeOffset;
+        myDescendantVariableIndex = item.myDescendantVariableIndex;
+        myDescendantVariant = item.myDescendantVariant;
+        myLevelDelta = item.myLevelDelta;
+        myAncestorIndex = item.myAncestorIndex;
+      }
+
+      public GeneticInformationItem Clone() {
+        return new GeneticInformationItem(this);
+      }
+
+      public static List<GeneticInformationItem> CopyList(List<GeneticInformationItem> list) {
+        List<GeneticInformationItem> result = new List<GeneticInformationItem>();
+        for (int i = 0; i < list.Count; i++)
+          result.Add(list[i]);
+        return result;
+      }
+
+      private static int CalculateAncestorIndex(SymbolicExpressionTreeNode Ancestor, SymbolicExpressionTreeNode Descendant) {
+        if (Ancestor == Descendant)
+          return 0;
+        // Node lastParent = Descendant, parent = Descendant.Parent;
+        // while (parent != Ancestor) {
+        //   lastParent = parent;
+        //   parent = parent.Parent;
+        //   if (parent == null)
+        //     throw new InvalidOperationException("Error in GeneticInformationItem: The given ancestor node does not seem to be an ancestor of the given descendant.");
+        // }
+        // // parent == Ancestor, lastParent is child of Ancestor
+        // int childIndex = 0;
+        // while (Ancestor.GetChild(childIndex) != lastParent)
+        //   childIndex++;
+        // return childIndex;
+        //
+        for (int i = 0; i < Ancestor.SubTrees.Count; i++)
+          if (treeContainsNode(Ancestor.SubTrees[i], Descendant))
+            return i;
+        return -1;
+      }
+
+      private static bool treeContainsNode(SymbolicExpressionTreeNode root, SymbolicExpressionTreeNode node) {
+        if (node == root)
+          return true;
+        foreach (SymbolicExpressionTreeNode subTree in root.SubTrees)
+          if(treeContainsNode(subTree, node))
+            return true;
+        return false;
+      }
+
+      public static GeneticInformationItem FindBestPendant(GeneticInformationItem Item, List<GeneticInformationItem> ComparisonItems,
+          StructuralSimilarityAnalysisParameters Parameters,
+          int MaxTreeHeight, int MaxTimeOffset,
+          out double BestPendantSimilarity) {
+        int maxSimilarityIndex = -1;
+        double similarity, maxSimilarity = -double.MaxValue;
+        for (int i = 0; i < ComparisonItems.Count; i++) {
+          similarity = Similarity(Item, ComparisonItems[i], Parameters, MaxTreeHeight, MaxTimeOffset);
+          if (!double.IsNaN(similarity) && similarity > maxSimilarity) {
+            maxSimilarity = similarity;
+            maxSimilarityIndex = i;
+          }
+        }
+        BestPendantSimilarity = maxSimilarity;
+        if (maxSimilarityIndex >= 0)
+          return ComparisonItems[maxSimilarityIndex];
+        else
+          return null;
+      }
+
+      public static double Similarity(GeneticInformationItem Item1, GeneticInformationItem Item2,
+          StructuralSimilarityAnalysisParameters Parameters,
+          int MaxTreeHeight, int MaxTimeOffset) {
+
+        if (Item1.AncestorDefinition != Item2.AncestorDefinition ||
+          Item1.DescendantDefinition != Item2.DescendantDefinition)
+          return double.NaN;
+
+        // the two items for sure have the same behavior definitions
+        #region init
+        double punishmentContributionSum = 0;
+        double punishmentCoefficientsProduct = 1;
+        double ancestorCoefficientDifferencePunishment = 0;
+        double ancestorTimeOffsetDifferencePunishment = 0;
+        double ancestorVariantDifferencePunishment = 0;
+        double ancestorVariableIndexDifferencePunishment = 0;
+        double descendantCoefficientDifferencePunishment = 0;
+        double descendantTimeOffsetDifferencePunishment = 0;
+        double descendantVariantDifferencePunishment = 0;
+        double descendantVariableIndexDifferencePunishment = 0;
+        double ancestorIndexDifferencePunishment = 0;
+        double levelDifferencePunishment = 0;
+        #endregion
+
+        ITerminalDefinition ancestorTerminal = Item1.AncestorDefinition as ITerminalDefinition;
+        ITerminalDefinition descendantTerminal = Item1.DescendantDefinition as ITerminalDefinition;
+        IFunctionDefinition ancestorFunction = Item1.AncestorDefinition as IFunctionDefinition;
+        IFunctionDefinition descendantFunction = Item1.DescendantDefinition as IFunctionDefinition;
+
+        if (Parameters.ConsiderLevelDifference) {
+          levelDifferencePunishment = Item1.LevelDelta - Item2.LevelDelta;
+          if (levelDifferencePunishment < 0)
+            levelDifferencePunishment = -levelDifferencePunishment;
+          levelDifferencePunishment /= MaxTreeHeight;
+          if (levelDifferencePunishment > 1)
+            levelDifferencePunishment = 1;
+          levelDifferencePunishment *= Parameters.LevelDifferenceCoefficient;
+          punishmentContributionSum += Parameters.LevelDifferenceCoefficient;
+          punishmentCoefficientsProduct *= (1 - Parameters.LevelDifferenceCoefficient);
+        }
+        if (Parameters.ConsiderAncestorIndex) {
+          if (Item1.AncestorIndex != Item2.AncestorIndex)
+            ancestorIndexDifferencePunishment = 1;
+          else
+            ancestorIndexDifferencePunishment = 0;
+          ancestorIndexDifferencePunishment *= Parameters.AncestorIndexCoefficient;
+          punishmentContributionSum += Parameters.AncestorIndexCoefficient;
+          punishmentCoefficientsProduct *= (1 - Parameters.AncestorIndexCoefficient);
+        }
+
+        if (Item1.AncestorDefinition is ITerminalDefinition) {
+          if (Parameters.ConsiderCoefficient) {
+            double coefficientDifference = Math.Abs(Item1.myAncestorCoefficient - Item2.myAncestorCoefficient);
+            if (ancestorTerminal.Parametrization.CoefficientIsGaussian)
+              ancestorCoefficientDifferencePunishment = (coefficientDifference / (ancestorTerminal.Parametrization.CoefficientSigma * 4));
+            else
+              ancestorCoefficientDifferencePunishment = (coefficientDifference / (ancestorTerminal.Parametrization.CoefficientMaxValue - ancestorTerminal.Parametrization.CoefficientMinValue));
+            if (ancestorCoefficientDifferencePunishment > 1)
+              ancestorCoefficientDifferencePunishment = 1;
+            ancestorCoefficientDifferencePunishment *= Parameters.CoefficientCoefficient;
+            punishmentContributionSum += Parameters.CoefficientCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.CoefficientCoefficient);
+          }
+          if (Parameters.ConsiderTimeOffset) {
+            double timeOffsetDifference = Math.Abs(Item1.AncestorTimeOffset - Item2.AncestorTimeOffset);
+            if (MaxTimeOffset > 0)
+              ancestorTimeOffsetDifferencePunishment = timeOffsetDifference / MaxTimeOffset;
+            ancestorTimeOffsetDifferencePunishment *= Parameters.TimeOffsetCoefficient;
+            punishmentContributionSum += Parameters.TimeOffsetCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.TimeOffsetCoefficient);
+          }
+          if (Parameters.ConsiderVariableIndex) {
+            if (Item1.AncestorVariableIndex != Item2.AncestorVariableIndex)
+              ancestorVariableIndexDifferencePunishment = 1;
+            else
+              ancestorVariableIndexDifferencePunishment = 0;
+            ancestorVariableIndexDifferencePunishment *= Parameters.VariableIndexCoefficient;
+            punishmentContributionSum += Parameters.VariableIndexCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.VariableIndexCoefficient);
+          }
+        } else {
+          if (Parameters.ConsiderVariant) {
+            if (Item1.AncestorVariant != Item2.AncestorVariant)
+              ancestorVariantDifferencePunishment = 1;
+            else
+              ancestorVariantDifferencePunishment = 0;
+            ancestorVariantDifferencePunishment *= Parameters.VariantCoefficient;
+            punishmentContributionSum += Parameters.VariantCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.VariantCoefficient);
+          }
+        }
+
+        if (Item1.DescendantDefinition is ITerminalDefinition) {
+          if (Parameters.ConsiderCoefficient) {
+            double coefficientDifference = Math.Abs(Item1.myDescendantCoefficient - Item2.myDescendantCoefficient);
+            if (descendantTerminal.Parametrization.CoefficientIsGaussian)
+              descendantCoefficientDifferencePunishment = (coefficientDifference / (descendantTerminal.Parametrization.CoefficientSigma * 4));
+            else
+              descendantCoefficientDifferencePunishment = (coefficientDifference / (descendantTerminal.Parametrization.CoefficientMaxValue - descendantTerminal.Parametrization.CoefficientMinValue));
+            if (descendantCoefficientDifferencePunishment > 1)
+              descendantCoefficientDifferencePunishment = 1;
+            descendantCoefficientDifferencePunishment *= Parameters.CoefficientCoefficient;
+            punishmentContributionSum += Parameters.CoefficientCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.CoefficientCoefficient);
+          }
+          if (Parameters.ConsiderTimeOffset) {
+            double timeOffsetDifference = Math.Abs(Item1.DescendantTimeOffset - Item2.DescendantTimeOffset);
+            if (MaxTimeOffset > 0)
+              descendantTimeOffsetDifferencePunishment = timeOffsetDifference / MaxTimeOffset;
+            descendantTimeOffsetDifferencePunishment *= Parameters.TimeOffsetCoefficient;
+            punishmentContributionSum += Parameters.TimeOffsetCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.TimeOffsetCoefficient);
+          }
+          if (Parameters.ConsiderVariableIndex) {
+            if (Item1.DescendantVariableIndex != Item2.DescendantVariableIndex)
+              descendantVariableIndexDifferencePunishment = 1;
+            else
+              descendantVariableIndexDifferencePunishment = 0;
+            descendantVariableIndexDifferencePunishment *= Parameters.VariableIndexCoefficient;
+            punishmentContributionSum += Parameters.VariableIndexCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.VariableIndexCoefficient);
+          }
+        } else {
+          if (Parameters.ConsiderVariant) {
+            if (Item1.DescendantVariant != Item2.DescendantVariant)
+              descendantVariantDifferencePunishment = 1;
+            else
+              descendantVariantDifferencePunishment = 0;
+            descendantVariantDifferencePunishment *= Parameters.VariantCoefficient;
+            punishmentContributionSum += Parameters.VariantCoefficient;
+            punishmentCoefficientsProduct *= (1 - Parameters.VariantCoefficient);
+          }
+        }
+
+        double result;
+
+        if (Parameters.AdditiveSimilarityCalculation) {
+          double punishmentsSum =
+            ancestorCoefficientDifferencePunishment + ancestorTimeOffsetDifferencePunishment +
+            ancestorVariantDifferencePunishment + ancestorVariableIndexDifferencePunishment +
+            descendantCoefficientDifferencePunishment + descendantTimeOffsetDifferencePunishment +
+            descendantVariantDifferencePunishment + descendantVariableIndexDifferencePunishment +
+            ancestorIndexDifferencePunishment + levelDifferencePunishment;
+          result = (1 - punishmentsSum / punishmentContributionSum);
+        } else {
+          result =
+            (1 - ancestorCoefficientDifferencePunishment) *
+            (1 - ancestorTimeOffsetDifferencePunishment) *
+            (1 - ancestorVariantDifferencePunishment) *
+            (1 - ancestorVariableIndexDifferencePunishment) *
+            (1 - descendantCoefficientDifferencePunishment) *
+            (1 - descendantTimeOffsetDifferencePunishment) *
+            (1 - descendantVariantDifferencePunishment) *
+            (1 - descendantVariableIndexDifferencePunishment) *
+            (1 - ancestorIndexDifferencePunishment) *
+            (1 - levelDifferencePunishment);
+          // worst possible result is (1-punishmentCoefficientsProduct), so scale linearly to [0;1]:
+          result = (result - punishmentCoefficientsProduct) / (1 - punishmentCoefficientsProduct);
+        }
+
+        if (result < 0 || result > 1)
+          throw new InvalidOperationException("ERROR in GeneticInformationItem.Similarity: An invalid similarity value (" + result.ToString() + ") has been calculated.");
+
+        return result;
+
+      }
+
+      public static List<GeneticInformationItem> GetGeneticInformationItems(SymbolicExpressionTreeNode Formula, int MinLevelDifference, int MaxLevelDifference) {
+        List<GeneticInformationItem> result = new List<GeneticInformationItem>();
+        List<SymbolicExpressionTreeNode> allNodes = new List<SymbolicExpressionTreeNode>();
+        allNodes.Add(Formula);
+        allNodes.AddRange(getDescendants(Formula));
+        foreach (SymbolicExpressionTreeNode node in allNodes) {
+          List<SymbolicExpressionTreeNode> allDescendants = new List<SymbolicExpressionTreeNode>();
+          allDescendants.Add(node);
+          allDescendants.AddRange(getDescendants(node));
+          foreach (SymbolicExpressionTreeNode descendant in allDescendants) {
+            GeneticInformationItem item = new GeneticInformationItem(node, descendant);
+            if (item.LevelDelta >= MinLevelDifference && item.LevelDelta <= MaxLevelDifference)
+              result.Add(item);
+          }
+        }
+        return result;
+      }
+
+      public static List<SymbolicExpressionTreeNode> getDescendants(SymbolicExpressionTreeNode node) {
+        List<SymbolicExpressionTreeNode> descendants = new List<SymbolicExpressionTreeNode>();
+        foreach (SymbolicExpressionTreeNode subTreeNode in node.SubTrees) {
+          addDescendants(descendants, subTreeNode);
+        }
+        return descendants;
+      }
+      private static void addDescendants(List<SymbolicExpressionTreeNode> list, SymbolicExpressionTreeNode node) {
+        list.Add(node);
+        foreach (SymbolicExpressionTreeNode subTreeNode in node.SubTrees) {
+          addDescendants(list, subTreeNode);
+        }
+      }
+
+    }
+
+    #endregion
+    */
+
+  }
+}
