Index: /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/EnumerableBoolEqualityComparer.cs
===================================================================
--- /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/EnumerableBoolEqualityComparer.cs	(revision 11667)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/EnumerableBoolEqualityComparer.cs	(revision 11667)
@@ -0,0 +1,50 @@
+﻿#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;
+
+namespace HeuristicLab.Algorithms.ParameterlessPopulationPyramid {
+  public class EnumerableBoolEqualityComparer : IEqualityComparer<IEnumerable<bool>> {
+    public bool Equals(IEnumerable<bool> first, IEnumerable<bool> second) {
+      return first.SequenceEqual(second);
+    }
+    public int GetHashCode(IEnumerable<bool> obj) {
+      int hash = 0;
+      int word = 1;
+      foreach (bool bit in obj) {
+        // load bits into an integer
+        word <<= 1;
+        word |= Convert.ToInt32(bit);
+        // only happens when the leading 1 reaches the sign bit
+        if (word < 0) {
+          // combine word into the hash
+          hash ^= word;
+          word = 1;
+        }
+      }
+      return hash;
+    }
+  }
+}
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 11666)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/HeuristicLab.Algorithms.ParameterlessPopulationPyramid-3.3.csproj	(revision 11667)
@@ -104,5 +104,7 @@
   <ItemGroup>
     <Compile Include="AlgorithmBase.cs" />
+    <Compile Include="EnumerableBoolEqualityComparer.cs" />
     <Compile Include="LinkageCrossover.cs" />
+    <Compile Include="Plugin.cs" />
     <Compile Include="Problems\DeceptiveTrapProblem.cs" />
     <Compile Include="HillClimber.cs" />
@@ -111,5 +113,4 @@
     <Compile Include="Population.cs" />
     <Compile Include="Problems\BinaryVectorProblem.cs" />
-    <Compile Include="Plugin.cs" />
     <Compile Include="Problems\EvaluationTracker.cs" />
     <Compile Include="Problems\HIFFProblem.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 11666)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageCrossover.cs	(revision 11667)
@@ -57,12 +57,12 @@
       if (changed) {
         double newFitness = problem.Evaluate(solution);
-        if (problem.IsBetter(newFitness, fitness)) {
-          // improvement made, keep change to solution
-          fitness = newFitness;
-        } else {
-          // revert solution
+        // if the original is strictly better, revert the change
+        if (problem.IsBetter(fitness, newFitness)) {
           foreach (var index in flipped) {
             solution[index] = !solution[index];
           }
+        } else {
+          // new solution is no worse than original, keep change to solution
+          fitness = newFitness;
         }
       }
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 11666)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/LinkageTree.cs	(revision 11667)
@@ -52,8 +52,6 @@
         // Swap element "i" with a random earlier element (including itself)
         int swapIndex = random.Next(i + 1);
-        yield return source[swapIndex];
-        source[swapIndex] = source[i];
-        // we don't actually perform the swap, we can forget about the
-        // swapped element because we already returned it.
+        source.Swap(i, swapIndex);
+        yield return source[i];
       }
       yield return source[0];
@@ -148,5 +146,4 @@
       var topLevel = Enumerable.Range(0, length).ToList();
       bool[] useful = Enumerable.Repeat(true, clusters.Length).ToArray();
-
 
       // Store the distances between all clusters
Index: /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs
===================================================================
--- /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs	(revision 11666)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/ParameterlessPopulationPyramid.cs	(revision 11667)
@@ -39,5 +39,5 @@
   [StorableClass]
   [Creatable("Parameterless Population Pyramid")]
-  
+
   public class ParameterlessPopulationPyramid : AlgorithmBase {
     private readonly IRandom random = new MersenneTwister();
@@ -46,5 +46,5 @@
 
     // Tracks all solutions in Pyramid for quick membership checks
-    private readonly HashSet<bool[]> seen = new HashSet<bool[]>();
+    private HashSet<bool[]> seen = new HashSet<bool[]>(new EnumerableBoolEqualityComparer());
 
     private const string MaximumIterationsParameterName = "Maximum Iterations";
@@ -53,5 +53,5 @@
       get { return (IFixedValueParameter<IntValue>)Parameters[MaximumIterationsParameterName]; }
     }
-    
+
     public int MaximumIterations {
       get { return MaximumIterationsParameter.Value.Value; }
@@ -70,5 +70,5 @@
     }
 
-    
+
     private const string SeedParameterName = "Seed";
 
@@ -149,5 +149,4 @@
     }
 
-
     private void AddIfUnique(bool[] solution, int level) {
       // Don't add things you have seen
@@ -156,6 +155,7 @@
         pyramid.Add(new Population(tracker.Length, random));
       }
-      pyramid[level].Add(solution);
-      seen.Add(solution);
+      var copied = (bool[])solution.Clone();
+      pyramid[level].Add(copied);
+      seen.Add(copied);
     }
 
@@ -169,4 +169,5 @@
       fitness = HillClimber.ImproveToLocalOptimum(tracker, solution, fitness, random);
       AddIfUnique(solution, 0);
+
       for (int level = 0; level < pyramid.Count; level++) {
         var current = pyramid[level];
@@ -184,4 +185,5 @@
       if (SetSeedRandomly) Seed = new System.Random().Next();
       pyramid = new List<Population>();
+      seen.Clear();
       random.Reset(Seed);
       tracker = new EvaluationTracker(Problem, MaximumEvaluations);
@@ -213,5 +215,5 @@
           ResultsQualitiesBest.Values.Add(tracker.BestQuality);
           ResultsQualitiesIteration.Values.Add(fitness);
-        }        
+        }
       }
     }
Index: /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/Plugin.cs.frame
===================================================================
--- /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/Plugin.cs.frame	(revision 11666)
+++ /branches/Parameter-less Population Pyramid/HeuristicLab.Algorithms.ParameterlessPopulationPyramid/3.3/Plugin.cs.frame	(revision 11667)
@@ -31,8 +31,15 @@
   [Plugin("HeuristicLab.Algorithms.ParameterlessPopulationPyramid", "3.3.10.$WCREV$")]
   [PluginFile("HeuristicLab.Algorithms.ParameterlessPopulationPyramid-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
   [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.BinaryVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
   [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
   public class Plugin : PluginBase {
   }
Index: /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/EnumerableBoolEqualityComparerTest.cs
===================================================================
--- /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/EnumerableBoolEqualityComparerTest.cs	(revision 11667)
+++ /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/EnumerableBoolEqualityComparerTest.cs	(revision 11667)
@@ -0,0 +1,115 @@
+﻿using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using HeuristicLab.Random;
+using System.Collections.Generic;
+using HeuristicLab.Algorithms.ParameterlessPopulationPyramid;
+using System.Linq;
+
+namespace ParameterlessPopulationPyramid.Test {
+  [TestClass]
+  public class EnumerableBoolEqualityComparerTest {
+    private static EnumerableBoolEqualityComparer compare = new EnumerableBoolEqualityComparer();
+    MersenneTwister rand = new MersenneTwister();
+
+    private void randFill(IList<bool> data, MersenneTwister rand) {
+      for (int i = 0; i < data.Count; i++) {
+        data[i] = rand.Next(2) == 1;
+      }
+    }
+    [TestMethod]
+    public void EnumerableBoolEqualsTest() {
+      bool[] array = new bool[10];
+      // Referencially equal
+      randFill(array, rand);
+      Assert.IsTrue(compare.Equals(array, array));
+      
+      // Clones equal
+      var another = (bool[])array.Clone();
+      Assert.IsTrue(compare.Equals(array, another));
+      
+      // Flipping a bit makes unequal
+      int flip = rand.Next(array.Length-1);
+      another[flip] = !another[flip];
+      Assert.IsFalse(compare.Equals(array, another));
+
+      // Equality doesn't depend on container
+      List<bool> list = new List<bool>(array);
+      Assert.IsTrue(compare.Equals(list, array));
+      Assert.IsFalse(compare.Equals(list, another));
+    }
+
+    [TestMethod]
+    public void EnumerableBoolHashCollisionTest() {
+      int collisions = 0;
+
+      bool[] array = new bool[100];
+      randFill(array, rand);
+      int original = compare.GetHashCode(array);
+      
+      bool[] another = (bool[])array.Clone();
+      // Perform random walk around string checking for hash collisions
+      for (int i = 0; i < array.Length * array.Length; i++) {
+        int flip = rand.Next(array.Length - 1);
+        another[flip] = !another[flip];
+        int hash = compare.GetHashCode(another);
+        if (hash == original) {
+          // unequal sequences with same hash value
+          if (!array.SequenceEqual(another)) collisions++;
+        } else {
+          // unequal hash should mean unequal sequence
+          Assert.IsFalse(array.SequenceEqual(another));
+        }
+        // Keep the walk from getting too far afield
+        if (i % array.Length == 0) {
+          another = (bool[])array.Clone();
+        }
+      }
+      // A very lose upper bound, this only fails if you get more than sqrt(N) collisions per attempt 
+      Assert.IsTrue(collisions < array.Length);
+    }
+
+    [TestMethod]
+    public void EnumerableBoolHashSetTest() {
+      HashSet<bool[]> set = new HashSet<bool[]>(compare);
+      bool[] array = new bool[40];
+      randFill(array, rand);
+      set.Add(array);
+
+      // Same object not added
+      set.Add(array);
+      Assert.AreEqual(1, set.Count);
+
+      // Copy of object not allowed
+      var another = (bool[])array.Clone();
+      set.Add(another);
+      Assert.AreEqual(1, set.Count);
+
+      // Flipping a bit makes unequal
+      int flip = rand.Next(array.Length - 1);
+      another[flip] = !another[flip];
+      set.Add(another);
+      Assert.AreEqual(2, set.Count);
+
+      // Add random solutions which are 1 bit different from array to the set
+      set.Clear();
+      List<bool[]> added = new List<bool[]>();
+      for (int i = 0; i < array.Length * 10; i++) {
+        // flip a bit at random
+        another = (bool[])array.Clone();
+        flip = rand.Next(array.Length - 1);
+        another[flip] = !another[flip];
+        bool unique = set.Add(another);
+        bool actuallyUnique = true;
+        foreach (var previous in added) {
+          if (previous.SequenceEqual(another)) {
+            actuallyUnique = false;
+          }
+        }
+        Assert.AreEqual(actuallyUnique, unique);
+        if (actuallyUnique) {
+          added.Add(another);
+        }
+      }
+    }
+  }
+}
Index: /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/ParameterlessPopulationPyramid.Test.csproj
===================================================================
--- /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/ParameterlessPopulationPyramid.Test.csproj	(revision 11666)
+++ /branches/Parameter-less Population Pyramid/ParameterlessPopulationPyramid.Test/ParameterlessPopulationPyramid.Test.csproj	(revision 11667)
@@ -63,4 +63,5 @@
   </Choose>
   <ItemGroup>
+    <Compile Include="EnumerableBoolEqualityComparerTest.cs" />
     <Compile Include="LinkageTreeTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
