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 11662)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HeuristicLab.Algorithms.ParameterlessPopulationPyramid-3.3.csproj	(revision 11663)
@@ -100,7 +100,9 @@
   <ItemGroup>
     <Compile Include="AlgorithmBase.cs" />
+    <Compile Include="LinkageCrossover.cs" />
     <Compile Include="DeceptiveTrapProblem.cs" />
     <Compile Include="HillClimber.cs" />
     <Compile Include="LinkageTree.cs" />
+    <Compile Include="Population.cs" />
     <Compile Include="Problems\BinaryVectorProblem.cs" />
     <Compile Include="Plugin.cs" />
Index: /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageCrossover.cs
===================================================================
--- /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageCrossover.cs	(revision 11663)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageCrossover.cs	(revision 11663)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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.Random;
+
+namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid {
+  public static class LinkageCrossover {
+
+    public static double ImproveUsingTree(LinkageTree tree, IList<bool[]> donors, bool[] solution, double fitness, BinaryVectorProblem problem, IRandom rand) {
+      var options = Enumerable.Range(0, donors.Count).ToArray();
+      foreach (var cluster in tree.Clusters) {
+        // Find a donor which has at least one gene value different
+        // from the current solution for this cluster of genes
+        bool donorFound = false;
+        foreach (var donorIndex in options.Shuffle(rand)) {
+          // Attempt the donation
+          fitness = Donate(solution, fitness, donors[donorIndex], cluster, problem, out donorFound);
+          if (donorFound) break;
+        }
+      }
+      return fitness;
+    }
+
+    private static double Donate(bool[] solution, double fitness, bool[] source, IEnumerable<int> cluster, BinaryVectorProblem problem, out bool changed) {
+      // keep track of which bits flipped to make the donation
+      List<int> flipped = new List<int>();
+      foreach (var index in cluster) {
+        if (solution[index] != source[index]) {
+          flipped.Add(index);
+          solution[index] = !solution[index];
+        }
+      }
+      changed = flipped.Count > 0;
+      if (changed) {
+        double newFitness = problem.Evaluate(solution);
+        if (problem.IsBetter(newFitness, fitness)) {
+          // improvement made, keep change to solution
+          fitness = newFitness;
+        } else {
+          // revert solution
+          foreach (var index in flipped) {
+            solution[index] = !solution[index];
+          }
+        }
+      }
+      return fitness;
+    }
+  }
+}
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 11662)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs	(revision 11663)
@@ -65,11 +65,15 @@
     private readonly int[][][] occurances;
     private readonly List<int>[] clusters;
-    private readonly List<int> clusterOrdering;
+    private List<int> clusterOrdering;
     private readonly int length;
-
-    public LinkageTree(int length) {
+    private readonly IRandom rand;
+    private bool rebuildRequired = false;
+
+    public LinkageTree(int length, IRandom rand) {
       this.length = length;
+      this.rand = rand;
       occurances = new int[length][][];
 
+      // Create a lower triangular matrix without the diagonal
       for (int i = 1; i < length; i++) {
         occurances[i] = new int[i][];
@@ -99,4 +103,5 @@
         }
       }
+      rebuildRequired = true;
     }
 
@@ -109,5 +114,4 @@
         var p = value / total;
         sum += (p * Math.Log(p));
-
       }
       return sum;
@@ -115,4 +119,5 @@
 
     private double EntropyDistance(int i, int j) {
+      // This ensures you are using the lower triangular part of "occurances"
       if (i < j) {
         int temp = i;
@@ -139,5 +144,5 @@
     }
 
-    public void Rebuild(IRandom rand) {
+    private void Rebuild() {
       // Keep track of which clusters have not been merged
       var topLevel = Enumerable.Range(0, length).ToList();
@@ -236,11 +241,19 @@
         if (useful[i]) clusterOrdering.Add(i);
       }
-      // TODO Shuffle cluster ordering
+
+      // Shuffle before sort to ensure ties are broken randomly
       clusterOrdering.ShuffleInPlace(rand);
-      clusterOrdering.Sort((i, j) => clusters[i].Count.CompareTo(clusters[j].Count));
-    }
-
-    public double ImproveUsingTree(bool[] solution, double fitness, BinaryVectorProblem problem) {
-      return fitness;
+      clusterOrdering = clusterOrdering.OrderBy(i => clusters[i].Count).ToList();
+    }
+
+    public IEnumerable<List<int>> Clusters {
+      get {
+        // Just in time rebuilding
+        if (rebuildRequired) Rebuild();
+        foreach (var index in clusterOrdering) {
+          // Send out the clusters in the desired order
+          yield return clusters[index];
+        }
+      }
     }
   }
Index: /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/Population.cs
===================================================================
--- /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/Population.cs	(revision 11663)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/Population.cs	(revision 11663)
@@ -0,0 +1,41 @@
+﻿#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;
+
+namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid {
+  public class Population {
+    private readonly List<bool[]> solutions = new List<bool[]>();
+    private LinkageTree tree;
+    public Population(int length, IRandom rand) {
+      tree = new LinkageTree(length, rand);
+    }
+    void Add(bool[] solution) {
+      solutions.Add(solution);
+      tree.Add(solution);
+    }
+  }
+}
Index: /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/LinkageTreeTest.cs
===================================================================
--- /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/LinkageTreeTest.cs	(revision 11662)
+++ /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/LinkageTreeTest.cs	(revision 11663)
@@ -19,4 +19,5 @@
     };
 
+    // These are the clusters that should be built using "solutions" and the seed 123
     private static int[][] correctClusters = new int[][] {
       new int[] { 2, 3 },
@@ -30,5 +31,6 @@
     [TestMethod]
     public void LinkageTreeTestAdd() {
-      LinkageTree tree = new LinkageTree(Length);
+      MersenneTwister rand = new MersenneTwister();
+      LinkageTree tree = new LinkageTree(Length, rand);
       tree.Add(solutions[0]);
       tree.Add(solutions[1]);
@@ -43,5 +45,6 @@
     [TestMethod]
     public void LinkageTreeTestEntropyDistance() {
-      LinkageTree tree = new LinkageTree(Length);
+      MersenneTwister rand = new MersenneTwister();
+      LinkageTree tree = new LinkageTree(Length, rand);
       PrivateObject hidden = new PrivateObject(tree);
       // No information should result in a distance of 0
@@ -63,18 +66,17 @@
     [TestMethod]
     public void LinkageTreeTestRebuild() {
-      LinkageTree tree = new LinkageTree(Length);
+      // The seed matters as equal sized clusters can appear in any order
+      MersenneTwister rand = new MersenneTwister(123);
+      LinkageTree tree = new LinkageTree(Length, rand);
       foreach (var solution in solutions) {
         tree.Add(solution);
       }
-      MersenneTwister rand = new MersenneTwister(123);
-      tree.Rebuild(rand);
-      PrivateObject hidden = new PrivateObject(tree);
-      var ordering = (List<int>)hidden.GetField("clusterOrdering");
-      var clusters = (List<int>[])hidden.GetField("clusters");
-      int[][] comparable = new int[ordering.Count][];
-      for (int i = 0; i < ordering.Count; i++) {
-        var found = clusters[ordering[i]].ToArray();
-        Array.Sort(found);
-        Assert.IsTrue(correctClusters[i].SequenceEqual(found));
+
+      // Check if the clusters created contain the expected variables.
+      var found = tree.Clusters.ToArray();
+      Assert.AreEqual(correctClusters.Length, found.Length);
+      for (int i = 0; i < found.Length; i++) {
+        found[i].Sort();
+        Assert.IsTrue(found[i].SequenceEqual(correctClusters[i]), string.Format("Failed On Cluster {0}", i));
       }
     }
