Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisBuildingBlockAnalyzer.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisBuildingBlockAnalyzer.cs	(revision 16262)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisBuildingBlockAnalyzer.cs	(revision 16263)
@@ -41,5 +41,5 @@
     private const string SimplifyTreesParameterName = "SimplifyTrees";
 
-    private Dictionary<int, DataRow> hashToRow = new Dictionary<int, DataRow>();
+    private Dictionary<ulong, DataRow> hashToRow = new Dictionary<ulong, DataRow>();
 
     #region parameters
@@ -66,5 +66,5 @@
       base.InitializeState();
 
-      hashToRow = new Dictionary<int, DataRow>();
+      hashToRow = new Dictionary<ulong, DataRow>();
     }
 
@@ -104,6 +104,6 @@
       var simplify = SimplifyTrees.Value;
 
-      var expressions = new Dictionary<int, string>();
-      var expressionCounts = new Dictionary<int, int>();
+      var expressions = new Dictionary<ulong, string>();
+      var expressionCounts = new Dictionary<ulong, int>();
 
       int totalCount = 0; // total number of examined subtrees
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs	(revision 16263)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDiversityPreservingCrossover.cs	(revision 16263)
@@ -0,0 +1,144 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+using static HeuristicLab.Problems.DataAnalysis.Symbolic.SymbolicExpressionHashExtensions;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [Item("DiversityCrossover", "Simple crossover operator prioritizing internal nodes according to the given probability.")]
+  [StorableClass]
+  public sealed class SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
+
+    private const string InternalCrossoverPointProbabilityParameterName = "InternalCrossoverPointProbability";
+    private const string WindowingParameterName = "Windowing";
+    private const string ProportionalSamplingParameterName = "ProportionalSampling";
+
+    #region Parameter Properties
+    public IValueLookupParameter<PercentValue> InternalCrossoverPointProbabilityParameter {
+      get { return (IValueLookupParameter<PercentValue>)Parameters[InternalCrossoverPointProbabilityParameterName]; }
+    }
+
+    public IValueLookupParameter<BoolValue> WindowingParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters[WindowingParameterName]; }
+    }
+
+    public IValueLookupParameter<BoolValue> ProportionalSamplingParameter {
+      get { return (IValueLookupParameter<BoolValue>)Parameters[ProportionalSamplingParameterName]; }
+    }
+    #endregion
+
+    #region Properties
+    public PercentValue InternalCrossoverPointProbability {
+      get { return InternalCrossoverPointProbabilityParameter.ActualValue; }
+    }
+
+    public BoolValue Windowing {
+      get { return WindowingParameter.ActualValue; }
+    }
+
+    public BoolValue ProportionalSampling {
+      get { return ProportionalSamplingParameter.ActualValue; }
+    }
+    #endregion
+
+    public SymbolicDataAnalysisExpressionDiversityPreservingCrossover() {
+      name = "DiversityCrossover";
+      Parameters.Add(new ValueLookupParameter<PercentValue>(InternalCrossoverPointProbabilityParameterName, "The probability to select an internal crossover point (instead of a leaf node).", new PercentValue(0.9)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>(WindowingParameterName, "Use proportional sampling with windowing for cutpoint selection.", new BoolValue(false)));
+      Parameters.Add(new ValueLookupParameter<BoolValue>(ProportionalSamplingParameterName, "Select cutpoints proportionally using probabilities as weights instead of randomly.", new BoolValue(true)));
+    }
+
+    private SymbolicDataAnalysisExpressionDiversityPreservingCrossover(SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T> original, Cloner cloner) : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionDiversityPreservingCrossover<T>(this, cloner);
+    }
+
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionDiversityPreservingCrossover(bool deserializing) : base(deserializing) { }
+
+    private static ISymbolicExpressionTreeNode ActualRoot(ISymbolicExpressionTree tree) {
+      return tree.Root.GetSubtree(0).GetSubtree(0);
+    }
+
+    public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, double internalCrossoverPointProbability, int maxLength, int maxDepth, bool windowing, bool proportionalSampling = false) {
+      var leafCrossoverPointProbability = 1 - internalCrossoverPointProbability;
+
+      var nodes0 = ActualRoot(parent0).MakeNodes().Sort();
+      var nodes1 = ActualRoot(parent1).MakeNodes().Sort();
+
+      IList<HashNode<ISymbolicExpressionTreeNode>> sampled0;
+      IList<HashNode<ISymbolicExpressionTreeNode>> sampled1;
+
+      if (proportionalSampling) {
+        var p = internalCrossoverPointProbability;
+        var weights0 = nodes0.Select(x => x.IsChild ? 1 - p : p);
+        sampled0 = nodes0.SampleProportionalWithoutRepetition(random, nodes0.Length, weights0, windowing: windowing).ToArray();
+
+        var weights1 = nodes1.Select(x => x.IsChild ? 1 - p : p);
+        sampled1 = nodes1.SampleProportionalWithoutRepetition(random, nodes1.Length, weights1, windowing: windowing).ToArray();
+      } else {
+        sampled0 = ChooseNodes(random, nodes0, internalCrossoverPointProbability).ShuffleInPlace(random);
+        sampled1 = ChooseNodes(random, nodes1, internalCrossoverPointProbability).ShuffleInPlace(random);
+      }
+
+      foreach (var selected in sampled0) {
+        var cutpoint = new CutPoint(selected.Data.Parent, selected.Data);
+
+        var maxAllowedDepth = maxDepth - parent0.Root.GetBranchLevel(selected.Data);
+        var maxAllowedLength = maxLength - (parent0.Length - selected.Data.GetLength());
+
+        foreach (var candidate in sampled1) {
+          if (candidate.CalculatedHashValue == selected.CalculatedHashValue
+            || candidate.Data.GetDepth() > maxAllowedDepth
+            || candidate.Data.GetLength() > maxAllowedLength
+            || !cutpoint.IsMatchingPointType(candidate.Data)) {
+            continue;
+          }
+
+          Swap(cutpoint, candidate.Data);
+          return parent0;
+        }
+      }
+      return parent0;
+    }
+
+    public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) {
+      if (this.ExecutionContext == null) {
+        throw new InvalidOperationException("ExecutionContext not set.");
+      }
+
+      var maxDepth = MaximumSymbolicExpressionTreeDepth.Value;
+      var maxLength = MaximumSymbolicExpressionTreeLength.Value;
+
+      var internalCrossoverPointProbability = InternalCrossoverPointProbability.Value;
+      var windowing = Windowing.Value;
+      var proportionalSampling = ProportionalSampling.Value;
+
+      return Cross(random, parent0, parent1, internalCrossoverPointProbability, maxLength, maxDepth, windowing, proportionalSampling);
+    }
+
+    private static List<HashNode<ISymbolicExpressionTreeNode>> ChooseNodes(IRandom random, IEnumerable<HashNode<ISymbolicExpressionTreeNode>> nodes, double internalCrossoverPointProbability) {
+      var list = new List<HashNode<ISymbolicExpressionTreeNode>>();
+
+      var chooseInternal = random.NextDouble() < internalCrossoverPointProbability;
+
+      if (chooseInternal) {
+        list.AddRange(nodes.Where(x => !x.IsChild && x.Data.Parent != null));
+      }
+      if (!chooseInternal || list.Count == 0) {
+        list.AddRange(nodes.Where(x => x.IsChild && x.Data.Parent != null));
+      }
+
+      return list;
+    }
+  }
+}
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/HashExtensions.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/HashExtensions.cs	(revision 16262)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/HashExtensions.cs	(revision 16263)
@@ -32,6 +32,6 @@
 
       public bool Enabled;
-      public int HashValue;           // the initial (fixed) hash value for this individual node/data
-      public int CalculatedHashValue; // the calculated hash value (taking into account the children hash values)
+      public ulong HashValue;           // the initial (fixed) hash value for this individual node/data
+      public ulong CalculatedHashValue; // the calculated hash value (taking into account the children hash values)
 
       public Action<HashNode<T>[], int> Simplify;
@@ -67,5 +67,6 @@
 
       public override int GetHashCode() {
-        return CalculatedHashValue;
+        //return CalculatedHashValue;
+        return Data.GetHashCode();
       }
 
@@ -79,7 +80,7 @@
     }
 
-    public static int ComputeHash<T>(this HashNode<T>[] nodes, int i) where T : class {
+    public static ulong ComputeHash<T>(this HashNode<T>[] nodes, int i) where T : class {
       var node = nodes[i];
-      var hashes = new int[node.Arity + 1];
+      var hashes = new ulong[node.Arity + 1];
       for (int j = i - 1, k = 0; k < node.Arity; j -= 1 + nodes[j].Size, k++) {
         hashes[k] = nodes[j].CalculatedHashValue;
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/HashUtil.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/HashUtil.cs	(revision 16262)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/HashUtil.cs	(revision 16263)
@@ -20,6 +20,4 @@
 #endregion
 
-using System;
-using System.Security.Cryptography;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -28,8 +26,8 @@
 
     // A simple hash function from Robert Sedgwicks Algorithms in C book.I've added some simple optimizations to the algorithm in order to speed up its hashing process. 
-    public static int RSHash(int[] input) {
+    public static ulong RSHash(ulong[] input) {
       const int b = 378551;
-      int a = 63689;
-      int hash = 0;
+      ulong a = 63689;
+      ulong hash = 0;
 
       foreach (var v in input) {
@@ -41,6 +39,6 @@
 
     // A bitwise hash function written by Justin Sobel
-    public static int JSHash(int[] input) {
-      int hash = 1315423911;
+    public static ulong JSHash(ulong[] input) {
+      ulong hash = 1315423911;
       for (int i = 0; i < input.Length; ++i)
         hash ^= (hash << 5) + input[i] + (hash >> 2);
@@ -49,7 +47,7 @@
 
     // This hash function comes from Brian Kernighan and Dennis Ritchie's book "The C Programming Language". It is a simple hash function using a strange set of possible seeds which all constitute a pattern of 31....31...31 etc, it seems to be very similar to the DJB hash function. 
-    public static int BKDRHash(int[] input) {
-      const int seed = 131;
-      int hash = 0;
+    public static ulong BKDRHash(ulong[] input) {
+      ulong seed = 131;
+      ulong hash = 0;
       foreach (var v in input) {
         hash = (hash * seed) + v;
@@ -59,6 +57,6 @@
 
     // This is the algorithm of choice which is used in the open source SDBM project. The hash function seems to have a good over-all distribution for many different data sets. It seems to work well in situations where there is a high variance in the MSBs of the elements in a data set. 
-    public static int SDBMHash(int[] input) {
-      int hash = 0;
+    public static ulong SDBMHash(ulong[] input) {
+      ulong hash = 0;
       foreach (var v in input) {
         hash = v + (hash << 6) + (hash << 16) - hash;
@@ -68,6 +66,6 @@
 
     // An algorithm produced by Professor Daniel J. Bernstein and shown first to the world on the usenet newsgroup comp.lang.c. It is one of the most efficient hash functions ever published. 
-    public static int DJBHash(int[] input) {
-      int hash = 5381;
+    public static ulong DJBHash(ulong[] input) {
+      ulong hash = 5381;
       foreach (var v in input) {
         hash = (hash << 5) + hash + v;
@@ -77,6 +75,6 @@
 
     // An algorithm proposed by Donald E.Knuth in The Art Of Computer Programming Volume 3, under the topic of sorting and search chapter 6.4. 
-    public static int DEKHash(int[] input) {
-      int hash = input.Length;
+    public static ulong DEKHash(ulong[] input) {
+      ulong hash = (ulong)input.Length;
       foreach (var v in input) {
         hash = (hash << 5) ^ (hash >> 27) ^ v;
@@ -85,23 +83,23 @@
     }
 
-    public static int CryptoHash(HashAlgorithm ha, int[] input) {
-      return BitConverter.ToInt32(ha.ComputeHash(input.ToByteArray()), 0);
-    }
+    //public static ulong CryptoHash(HashAlgorithm ha, ulong[] input) {
+    //  return BitConverter.ToInt32(ha.ComputeHash(input.ToByteArray()), 0);
+    //}
 
-    public static byte[] ToByteArray(this int[] input) {
-      var bytes = new byte[input.Length * sizeof(int)];
-      int pos = 0;
-      foreach (var v in input) {
-        var b0 = (byte)((v >> 24) & 0xFF);
-        var b1 = (byte)((v >> 16) & 0xFF);
-        var b2 = (byte)((v >> 8) & 0xFF);
-        var b3 = (byte)(v & 0xFF);
-        bytes[pos++] = b0;
-        bytes[pos++] = b1;
-        bytes[pos++] = b2;
-        bytes[pos++] = b3;
-      }
-      return bytes;
-    }
+    //public static byte[] ToByteArray(this ulong[] input) {
+    //  var bytes = new byte[input.Length * sizeof(int)];
+    //  int pos = 0;
+    //  foreach (var v in input) {
+    //    var b0 = (byte)((v >> 24) & 0xFF);
+    //    var b1 = (byte)((v >> 16) & 0xFF);
+    //    var b2 = (byte)((v >> 8) & 0xFF);
+    //    var b3 = (byte)(v & 0xFF);
+    //    bytes[pos++] = b0;
+    //    bytes[pos++] = b1;
+    //    bytes[pos++] = b2;
+    //    bytes[pos++] = b3;
+    //  }
+    //  return bytes;
+    //}
   }
 }
Index: /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/SymbolicExpressionTreeHash.cs
===================================================================
--- /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/SymbolicExpressionTreeHash.cs	(revision 16262)
+++ /trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Hashing/SymbolicExpressionTreeHash.cs	(revision 16263)
@@ -39,10 +39,10 @@
     private static readonly ISymbolicExpressionTreeNodeComparer comparer = new SymbolicExpressionTreeNodeComparer();
 
-    public static int ComputeHash(this ISymbolicExpressionTree tree) {
+    public static ulong ComputeHash(this ISymbolicExpressionTree tree) {
       return ComputeHash(tree.Root.GetSubtree(0).GetSubtree(0));
     }
 
     // compute node hashes without sorting the arguments
-    public static Dictionary<ISymbolicExpressionTreeNode, int> ComputeNodeHashes(this ISymbolicExpressionTree tree) {
+    public static Dictionary<ISymbolicExpressionTreeNode, ulong> ComputeNodeHashes(this ISymbolicExpressionTree tree) {
       var root = tree.Root.GetSubtree(0).GetSubtree(0);
       var nodes = root.MakeNodes();
@@ -57,16 +57,17 @@
     }
 
-    public static int ComputeHash(this ISymbolicExpressionTreeNode treeNode) {
+    public static ulong ComputeHash(this ISymbolicExpressionTreeNode treeNode) {
       var hashNodes = treeNode.MakeNodes();
       var simplified = hashNodes.Simplify();
-      return ComputeHash(simplified);
-    }
-
-    public static int ComputeHash(this HashNode<ISymbolicExpressionTreeNode>[] nodes) {
-      int hash = 1315423911;
-      foreach (var node in nodes)
-        hash ^= (hash << 5) + node.CalculatedHashValue + (hash >> 2);
-      return hash;
-    }
+      //return ComputeHash(simplified);
+      return simplified.Last().CalculatedHashValue;
+    }
+
+    //public static int ComputeHash(this HashNode<ISymbolicExpressionTreeNode>[] nodes) {
+    //  int hash = 1315423911;
+    //  foreach (var node in nodes)
+    //    hash ^= (hash << 5) + node.CalculatedHashValue + (hash >> 2);
+    //  return hash;
+    //}
 
     public static HashNode<ISymbolicExpressionTreeNode> ToHashNode(this ISymbolicExpressionTreeNode node) {
@@ -77,5 +78,5 @@
         name = variableTreeNode.VariableName;
       }
-      var hash = name.GetHashCode();
+      var hash = (ulong)name.GetHashCode();
       var hashNode = new HashNode<ISymbolicExpressionTreeNode>(comparer) {
         Data = node,
