Index: branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/DeceptiveTrapProblem.cs
===================================================================
--- branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/DeceptiveTrapProblem.cs	(revision 11640)
+++ branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/DeceptiveTrapProblem.cs	(revision 11656)
@@ -1,3 +1,24 @@
-﻿using System;
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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;
Index: branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HeuristicLab.Algorithms.ParameterlessPopulationPyramid-3.3.csproj
===================================================================
--- branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HeuristicLab.Algorithms.ParameterlessPopulationPyramid-3.3.csproj	(revision 11640)
+++ branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HeuristicLab.Algorithms.ParameterlessPopulationPyramid-3.3.csproj	(revision 11656)
@@ -102,4 +102,5 @@
     <Compile Include="DeceptiveTrapProblem.cs" />
     <Compile Include="HillClimber.cs" />
+    <Compile Include="LinkageTree.cs" />
     <Compile Include="Problems\BinaryVectorProblem.cs" />
     <Compile Include="Plugin.cs" />
Index: branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs
===================================================================
--- branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs	(revision 11656)
+++ branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs	(revision 11656)
@@ -0,0 +1,246 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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;
+using System.Text;
+using System.Threading.Tasks;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Random;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid {
+  public static class ListExtensions {
+    public static IList<T> Swap<T>(this IList<T> list, int indexA, int indexB) {
+      T tmp = list[indexA];
+      list[indexA] = list[indexB];
+      list[indexB] = tmp;
+      return list;
+    }
+    public static IList<T> ShuffleInPlace<T>(this IList<T> list, IRandom random) {
+      return list.ShuffleInPlace(random, 0, list.Count);
+    }
+    public static IList<T> ShuffleInPlace<T>(this IList<T> list, IRandom random, int maxIndex) {
+      return list.ShuffleInPlace(random, 0, maxIndex);
+    }
+    public static IList<T> ShuffleInPlace<T>(this IList<T> list, IRandom random, int minIndex, int maxIndex) {
+      for (int i = list.Count - 1; i > 0; i--) {
+        int swapIndex = random.Next(i + 1);
+        list.Swap(i, swapIndex);
+      }
+      return list;
+    }
+    
+  }
+  public class LinkageTree {
+
+    private int[][][] occurances;
+    private List<int>[] clusters;
+    private List<int> cluster_ordering;
+    private readonly int Length;
+
+    public LinkageTree(int length) {
+      Length = length;
+      occurances = new int[Length][][];
+
+      for (int i = 1; i < Length; i++) {
+        occurances[i] = new int[i][];
+        for (int j = 0; j < i; j++) {
+          occurances[i][j] = new int[4];
+        }
+      }
+      clusters = new List<int>[2 * Length - 1];
+      for (int i = 0; i < clusters.Length; i++) {
+        clusters[i] = new List<int>();
+      }
+
+      // first "length" clusters just contain a single gene
+      for (int i = 0; i < Length; i++) {
+        clusters[i].Add(i);
+      }
+    }
+
+    public void Add(bool[] solution) {
+      if (solution.Length != Length) throw new ArgumentException("The individual has not the correct length.");
+      for (int i = 1; i < solution.Length; i++) {
+        for (int j = 0; j < i; j++) {
+          // Updates the entry of the 4 long array based on the two bits
+          var pattern = (Convert.ToInt32(solution[j]) << 1) + Convert.ToInt32(solution[i]);
+          occurances[i][j][pattern]++;
+        }
+      }
+    }
+
+    // While "total" always has an integer value, it is a double to reduce
+    // how often type casts are needed to prevent integer divison
+    private static double NegativeEntropy(int[] counts, double total) {
+      double sum = 0;
+      double p;
+      foreach (var value in counts) {
+        if (value != 0) {
+          p = value / total;
+          sum += (p * Math.Log(p));
+        }
+      }
+      return sum;
+    }
+    
+    private double EntropyDistance(int i, int j) {
+      if (i < j) {
+        int temp = i;
+        i = j;
+        j = temp;
+      }
+      var entry = occurances[i][j];
+      int[] bits = new int[4];
+      // extracts the occurrences of the individual bits
+      bits[0] = entry[0] + entry[2];  // i zero
+      bits[1] = entry[1] + entry[3];  // i one
+      bits[2] = entry[0] + entry[1];  // j zero
+      bits[3] = entry[2] + entry[3];  // j one
+      double total = bits[0] + bits[1];
+      // entropy of the two bits on their own
+      double separate = NegativeEntropy(bits, total);
+      // entropy of the two bits as a single unit
+      double together = NegativeEntropy(entry, total);
+      // If together there is 0 entropy, the distance is zero
+      double ratio = 0;
+      if (together != 0) {
+        ratio = 2 - (separate / together);
+      }
+      return ratio;
+    }
+
+    public void Rebuild(IRandom rand) {
+      // Keep track of which clusters have not been merged
+      List<int> topLevel = new List<int>(Length);
+      for (int i = 0; i < Length; i++) {
+        topLevel.Add(i);
+      }
+      bool[] useful = new bool[clusters.Length];
+      for (int i = 0; i < useful.Length; i++) {
+        useful[i] = true;
+      }
+
+      // Store the distances between all clusters
+      double[,] distances = new double[clusters.Length, clusters.Length];
+      for (int i = 1; i < Length; i++) {
+        for (int j = 0; j < i; j++) {
+          distances[i, j] = EntropyDistance(clusters[i][0], clusters[j][0]);
+          // make it symmetric
+          distances[j, i] = distances[i, j];
+        }
+      }
+      // Each iteration we add some amount to the path, and remove the last
+      // two elements.  This keeps track of how much of usable is in the path.
+      int end_of_path = 0;
+
+      // build all clusters of size greater than 1
+      for (int index = Length; index < clusters.Length; index++) {
+        // Shuffle everything not yet in the path
+        topLevel.ShuffleInPlace(rand, end_of_path, topLevel.Count);
+
+        // if nothing in the path, just add a random usable node
+        if (end_of_path == 0) {
+          end_of_path = 1;
+        }
+        while (end_of_path < topLevel.Count) {
+          // last node in the path
+          int final = topLevel[end_of_path - 1];
+
+          // best_index stores the location of the best thing in the top level
+          int best_index = end_of_path;
+          double min_dist = distances[final, topLevel[best_index]];
+          // check all options which might be closer to "final" than "topLevel[best_index]"
+          for (int option = end_of_path + 1; option < topLevel.Count; option++) {
+            if (distances[final, topLevel[option]] < min_dist) {
+              min_dist = distances[final, topLevel[option]];
+              best_index = option;
+            }
+          }
+          // If the current last two in the path are minimally distant
+          if (end_of_path > 1 && min_dist >= distances[final, topLevel[end_of_path - 2]]) {
+            break;
+          }
+
+          // move the best to the end of the path
+          topLevel.Swap(end_of_path, best_index);
+          end_of_path++;
+
+        }
+        // Last two elements in the path are the clusters to join
+        int first = topLevel[end_of_path - 2];
+        int second = topLevel[end_of_path - 1];
+
+        // Only keep a cluster if the distance between the joining clusters is > zero
+        bool keep = !distances[first, second].IsAlmost(0d);
+        useful[first] = keep;
+        useful[second] = keep;
+
+        // create the new cluster
+        clusters[index] = clusters[first].Concat(clusters[second]).ToList();
+        // Calculate distances from all clusters to the newly created cluster
+        int i = 0;
+        int end = topLevel.Count - 1;
+        while (i <= end) {
+          int x = topLevel[i];
+          // Moves 'first' and 'second' to after "end" in topLevel
+          if (x == first || x == second) {
+            topLevel.Swap(i, end);
+            end--;
+            continue;
+          }
+          // Use the previous distances to calculate the joined distance
+          double first_distance = distances[first, x];
+          first_distance *= clusters[first].Count;
+          double second_distance = distances[second, x];
+          second_distance *= clusters[second].Count;
+          distances[x, index] = ((first_distance + second_distance)
+              / (clusters[first].Count + clusters[second].Count));
+          // make it symmetric
+          distances[index, x] = distances[x, index];
+          i++;
+        }
+
+        // Remove first and second from the path
+        end_of_path -= 2;
+        topLevel.RemoveAt(topLevel.Count - 1);
+        topLevel[topLevel.Count - 1] = index;
+      }
+      // Extract the useful clusters
+      cluster_ordering = new List<int>();
+      // Add all useful clusters. The last one is never useful.
+      for (int i = 0; i < useful.Length - 1; i++) {
+        if (useful[i]) cluster_ordering.Add(i);
+      }
+      // TODO Shuffle cluster ordering
+      cluster_ordering.ShuffleInPlace(rand);
+      cluster_ordering.Sort((i, j) => clusters[i].Count.CompareTo(clusters[j].Count));
+    }
+
+    public double ImproveUsingTree(bool[] solution, double fitness, BinaryVectorProblem problem) {
+      return fitness;
+    }
+  }
+}
