Index: trunk/sources/HeuristicLab 3.3.sln
===================================================================
--- trunk/sources/HeuristicLab 3.3.sln	(revision 14662)
+++ trunk/sources/HeuristicLab 3.3.sln	(revision 14663)
@@ -420,5 +420,5 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Algorithms.CMAEvolutionStrategy-3.4", "HeuristicLab.Algorithms.CMAEvolutionStrategy\3.4\HeuristicLab.Algorithms.CMAEvolutionStrategy-3.4.csproj", "{291010E4-2F4E-4D29-A795-753CFF293FDB}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Encodings.LinearLinkageEncoding-3.4", "HeuristicLab.Encodings.LinearLinkageEncoding\3.3\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj", "{BE698769-975A-429E-828C-72BB2B6182C8}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Encodings.LinearLinkageEncoding-3.4", "HeuristicLab.Encodings.LinearLinkageEncoding\3.4\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj", "{BE698769-975A-429E-828C-72BB2B6182C8}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.Orienteering-3.3", "HeuristicLab.Problems.Orienteering\3.3\HeuristicLab.Problems.Orienteering-3.3.csproj", "{D1EFA4CC-909F-41D5-9C1F-C3AF1957A372}"
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/ExactGroupsLinearLinkageCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/ExactGroupsLinearLinkageCreator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/ExactGroupsLinearLinkageCreator.cs	(revision 14663)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Exactgroups Linear Linkage Creator", "Creates a random linear linkage LLE encoded solution with a given number of equal-sized groups.")]
+  [StorableClass]
+  public sealed class ExactGroupsLinearLinkageCreator : LinearLinkageCreator {
+
+    public IValueLookupParameter<IntValue> ExactGroupsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["ExactGroups"]; }
+    }
+
+    public IntValue ExactGroups {
+      get { return ExactGroupsParameter.Value; }
+      set { ExactGroupsParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    private ExactGroupsLinearLinkageCreator(bool deserializing) : base(deserializing) { }
+    private ExactGroupsLinearLinkageCreator(ExactGroupsLinearLinkageCreator original, Cloner cloner) : base(original, cloner) { }
+
+    public ExactGroupsLinearLinkageCreator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("ExactGroups", "The exact number of equal-sized groups to create.", new IntValue(3)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExactGroupsLinearLinkageCreator(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, int length, int groups) {
+      var groupNumbers = Enumerable.Range(0, length).Select(x => x % groups).Shuffle(random);
+      var grouping = Enumerable.Range(0, groups).Select(x => new List<int>()).ToList();
+      var idx = 0;
+      foreach (var g in groupNumbers)
+        grouping[g].Add(idx++);
+
+      return LinearLinkage.FromGroups(length, grouping);
+    }
+
+    protected override LinearLinkage Create(IRandom random, int length) {
+      var groups = ExactGroupsParameter.ActualValue.Value;
+      return Apply(random, length, groups);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/MaxGroupSizeLinearLinkageCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/MaxGroupSizeLinearLinkageCreator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/MaxGroupSizeLinearLinkageCreator.cs	(revision 14663)
@@ -0,0 +1,52 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding.Creators {
+  [Item("Max Group-size Linear Linkage Creator", "Creates a random linear linkage LLE encoded solution with a given maximum number of items per group.")]
+  [StorableClass]
+  public class MaxGroupSizeLinearLinkageCreator: LinearLinkageCreator {
+
+    public IValueLookupParameter<IntValue> MaxGroupSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaxGroupSize"]; }
+    }
+
+    public IntValue MaxGroupSize {
+      get { return MaxGroupSizeParameter.Value; }
+      set { MaxGroupSizeParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected MaxGroupSizeLinearLinkageCreator(bool deserializing) : base(deserializing) { }
+    protected MaxGroupSizeLinearLinkageCreator(MaxGroupSizeLinearLinkageCreator original, Cloner cloner) : base(original, cloner) { }
+
+    public MaxGroupSizeLinearLinkageCreator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaxGroupSize", "The maximum number items in every group.", new IntValue(4)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MaxGroupSizeLinearLinkageCreator(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, int length, int maxGroupSize) {
+      var groups = Enumerable.Range(0, length).Select(x => new { Item = x, Group = random.Next(length)})
+        .GroupBy(x => x.Group)
+        .SelectMany(x => 
+           x.Select((y, i) => new {SubGroup = i%maxGroupSize, y.Item})
+            .GroupBy(y=>y.SubGroup)
+            .Select(y=>
+              y.Select(z=>z.Item).ToList()));
+      return LinearLinkage.FromGroups(length, groups);
+    }
+
+    protected override LinearLinkage Create(IRandom random, int length) {
+      var maxGroupSize = MaxGroupSizeParameter.ActualValue.Value;
+      return Apply(random, length, maxGroupSize);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/MaxGroupsLinearLinkageCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/MaxGroupsLinearLinkageCreator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/MaxGroupsLinearLinkageCreator.cs	(revision 14663)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Maxgroups Linear Linkage Creator", "Creates a random linear linkage LLE encoded solution with a given maximum number of groups.")]
+  [StorableClass]
+  public sealed class MaxGroupsLinearLinkageCreator : LinearLinkageCreator {
+
+    public IValueLookupParameter<IntValue> MaxGroupsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaxGroups"]; }
+    }
+
+    public IntValue MaxGroups {
+      get { return MaxGroupsParameter.Value; }
+      set { MaxGroupsParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    private MaxGroupsLinearLinkageCreator(bool deserializing) : base(deserializing) { }
+    private MaxGroupsLinearLinkageCreator(MaxGroupsLinearLinkageCreator original, Cloner cloner) : base(original, cloner) { }
+
+    public MaxGroupsLinearLinkageCreator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaxGroups", "The maximum number of groups to create.", new IntValue(3)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MaxGroupsLinearLinkageCreator(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, int length, int maxGroups) {
+      var groups = Enumerable.Range(0, length).Select(x => Tuple.Create(x, random.Next(maxGroups)))
+                                              .GroupBy(x => x.Item2)
+                                              .Select(x => x.Select(y => y.Item1).ToList());
+      return LinearLinkage.FromGroups(length, groups);
+    }
+
+    protected override LinearLinkage Create(IRandom random, int length) {
+      var maxGroups = MaxGroupsParameter.ActualValue.Value;
+      return Apply(random, length, maxGroups);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/RandomLinearLinkageCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/RandomLinearLinkageCreator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Creators/RandomLinearLinkageCreator.cs	(revision 14663)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Random Linear Linkage Creator", "Creates a random linear linkage LLE encoded solution (similar to MaxGroups set to N).")]
+  [StorableClass]
+  public sealed class RandomLinearLinkageCreator : LinearLinkageCreator {
+
+    [StorableConstructor]
+    private RandomLinearLinkageCreator(bool deserializing) : base(deserializing) { }
+    private RandomLinearLinkageCreator(RandomLinearLinkageCreator original, Cloner cloner) : base(original, cloner) { }
+    public RandomLinearLinkageCreator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RandomLinearLinkageCreator(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, int length) {
+      var groups = Enumerable.Range(0, length).Select(x => Tuple.Create(x, random.Next(length)))
+                                              .GroupBy(x => x.Item2)
+                                              .Select(x => x.Select(y => y.Item1).ToList());
+      return LinearLinkage.FromGroups(length, groups);
+    }
+
+    protected override LinearLinkage Create(IRandom random, int length) {
+      return Apply(random, length);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/GreedyPartitionCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/GreedyPartitionCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/GreedyPartitionCrossover.cs	(revision 14663)
@@ -0,0 +1,76 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Greedy Partition Crossover", "The Greedy Partition Crossover (GPX) is implemented as described in Ülker, Ö., Özcan, E., Korkmaz, E. E. 2007. Linear linkage encoding in grouping problems: applications on graph coloring and timetabling. In Practice and Theory of Automated Timetabling VI, pp. 347-363. Springer Berlin Heidelberg.")]
+  [StorableClass]
+  public sealed class GreedyPartitionCrossover : LinearLinkageCrossover {
+
+    [StorableConstructor]
+    private GreedyPartitionCrossover(bool deserializing) : base(deserializing) { }
+    private GreedyPartitionCrossover(GreedyPartitionCrossover original, Cloner cloner) : base(original, cloner) { }
+    public GreedyPartitionCrossover() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GreedyPartitionCrossover(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, ItemArray<LinearLinkage> parents) {
+      var len = parents[0].Length;
+      var childGroup = new List<HashSet<int>>();
+      var currentParent = random.Next(parents.Length);
+      var groups = parents.Select(x => x.GetGroups().Select(y => new HashSet<int>(y)).ToList()).ToList();
+      bool remaining;
+      do {
+        var maxGroup = groups[currentParent].Select((v, i) => Tuple.Create(i, v))
+          .MaxItems(x => x.Item2.Count)
+          .SampleRandom(random).Item1;
+        var group = groups[currentParent][maxGroup];
+        groups[currentParent].RemoveAt(maxGroup);
+        childGroup.Add(group);
+
+        remaining = false;
+        for (var p = 0; p < groups.Count; p++) {
+          for (var j = 0; j < groups[p].Count; j++) {
+            foreach (var elem in group) groups[p][j].Remove(elem);
+            if (!remaining && groups[p][j].Count > 0) remaining = true;
+          }
+        }
+
+        currentParent = (currentParent + 1) % parents.Length;
+      } while (remaining);
+
+      return LinearLinkage.FromGroups(len, childGroup);
+    }
+
+    protected override LinearLinkage Cross(IRandom random, ItemArray<LinearLinkage> parents) {
+      return Apply(random, parents);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/GroupCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/GroupCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/GroupCrossover.cs	(revision 14663)
@@ -0,0 +1,85 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Group Crossover", "The Group Crossover is implemented as described in Korkmaz, E.E. 2010. Multi-objective Genetic Algorithms for grouping problems. Applied Intelligence 33(2), pp. 179-192.")]
+  [StorableClass]
+  public sealed class GroupCrossover : LinearLinkageCrossover {
+
+    [StorableConstructor]
+    private GroupCrossover(bool deserializing) : base(deserializing) { }
+    private GroupCrossover(GroupCrossover original, Cloner cloner) : base(original, cloner) { }
+    public GroupCrossover() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GroupCrossover(this, cloner);
+    }
+    
+    public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) {
+      var length = p1.Length;
+      var lleeP1 = p1.ToEndLinks();
+      var lleeP2 = p2.ToEndLinks();
+      var lleeChild = new int[length];
+      var isTransfered = new bool[length];
+
+      for (var i = p1.Length - 1; i >= 0; i--) {
+        lleeChild[i] = i;
+
+        // Step 1
+        var isEndP1 = p1[i] == i;
+        var isEndP2 = p2[i] == i;
+        if (isEndP1 & isEndP2 || (isEndP1 | isEndP2 && random.NextDouble() < 0.5)) {
+          isTransfered[i] = true;
+          continue;
+        }
+
+        // Step 2
+        var end1 = lleeP1[i];
+        var end2 = lleeP2[i];
+
+        if (isTransfered[end1] & isTransfered[end2]) {
+          var end = random.NextDouble() < 0.5 ? end1 : end2;
+          lleeChild[i] = end;
+        } else if (isTransfered[end1]) {
+          lleeChild[i] = end1;
+        } else if (isTransfered[end2]) {
+          lleeChild[i] = end2;
+        } else {
+          var next = random.NextDouble() < 0.5 ? p1[i] : p2[i];
+          var end = lleeChild[next];
+          lleeChild[i] = end;
+        }
+      }
+      return LinearLinkage.FromEndLinks(lleeChild);
+    }
+
+    protected override LinearLinkage Cross(IRandom random, ItemArray<LinearLinkage> parents) {
+      if (parents.Length != 2) throw new InvalidOperationException(Name + ": Can only cross exactly two parents.");
+      return Apply(random, parents[0], parents[1]);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/LowestIndexFirstCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/LowestIndexFirstCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/LowestIndexFirstCrossover.cs	(revision 14663)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Lowest Index First Crossover", "The Lowest Index First Crossover (LIFX) is implemented as described in Ülker, Ö., Özcan, E., Korkmaz, E. E. 2007. Linear linkage encoding in grouping problems: applications on graph coloring and timetabling. In Practice and Theory of Automated Timetabling VI, pp. 347-363. Springer Berlin Heidelberg.")]
+  [StorableClass]
+  public sealed class LowestIndexFirstCrossover : LinearLinkageCrossover {
+
+    [StorableConstructor]
+    private LowestIndexFirstCrossover(bool deserializing) : base(deserializing) { }
+    private LowestIndexFirstCrossover(LowestIndexFirstCrossover original, Cloner cloner) : base(original, cloner) { }
+    public LowestIndexFirstCrossover() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LowestIndexFirstCrossover(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, ItemArray<LinearLinkage> parents) {
+      var len = parents[0].Length;
+      var p = random.Next(parents.Length);
+      var child = LinearLinkage.SingleElementGroups(len);
+      var remaining = new SortedSet<int>(Enumerable.Range(0, len));
+      do {
+        var i = remaining.Min;
+        foreach (var g in parents[p].GetGroupForward(i)) {
+          if (!remaining.Contains(g)) continue;
+          child[i] = g;
+          i = g;
+          remaining.Remove(g);
+        }
+        child[i] = i;
+        remaining.Remove(i);
+
+        p = (p + 1) % parents.Length;
+      } while (remaining.Count > 0);
+
+      return child;
+    }
+
+    protected override LinearLinkage Cross(IRandom random, ItemArray<LinearLinkage> parents) {
+      return Apply(random, parents);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/LowestIndexMaxCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/LowestIndexMaxCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/LowestIndexMaxCrossover.cs	(revision 14663)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Lowest Index Max Crossover", "The Lowest Index Max Crossover (LIMX) is implemented as described in Ülker, Ö., Özcan, E., Korkmaz, E. E. 2007. Linear linkage encoding in grouping problems: applications on graph coloring and timetabling. In Practice and Theory of Automated Timetabling VI, pp. 347-363. Springer Berlin Heidelberg.")]
+  [StorableClass]
+  public sealed class LowestIndexMaxCrossover : LinearLinkageCrossover {
+
+    [StorableConstructor]
+    private LowestIndexMaxCrossover(bool deserializing) : base(deserializing) { }
+    private LowestIndexMaxCrossover(LowestIndexMaxCrossover original, Cloner cloner) : base(original, cloner) { }
+    public LowestIndexMaxCrossover() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LowestIndexMaxCrossover(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, ItemArray<LinearLinkage> parents) {
+      var len = parents[0].Length;
+      var child = LinearLinkage.SingleElementGroups(len);
+      var remaining = new SortedSet<int>(Enumerable.Range(0, len));
+      do {
+        var groups = parents.Select(x => x.GetGroupForward(remaining.Min).Where(y => remaining.Contains(y)).ToList()).ToList();
+        var max = groups.Select((v, idx) => Tuple.Create(idx, v.Count)).MaxItems(x => x.Item2).SampleRandom(random).Item1;
+        var i = groups[max][0];
+        for (var k = 1; k < groups[max].Count; k++) {
+          child[i] = groups[max][k];
+          remaining.Remove(i);
+          i = child[i];
+        }
+        child[i] = i;
+        remaining.Remove(i);
+      } while (remaining.Count > 0);
+
+      return child;
+    }
+
+    protected override LinearLinkage Cross(IRandom random, ItemArray<LinearLinkage> parents) {
+      return Apply(random, parents);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/MultiLLECrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/MultiLLECrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/MultiLLECrossover.cs	(revision 14663)
@@ -0,0 +1,100 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Reflection;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Multi LLE Crossover", "Randomly selects and applies one of its crossovers every time it is called.")]
+  [StorableClass]
+  public class MultiLinearLinkageCrossover : StochasticMultiBranch<ILinearLinkageCrossover>, ILinearLinkageCrossover, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public IScopeTreeLookupParameter<LinearLinkage> ParentsParameter {
+      get { return (IScopeTreeLookupParameter<LinearLinkage>)Parameters["Parents"]; }
+    }
+
+    public ILookupParameter<LinearLinkage> ChildParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["Child"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiLinearLinkageCrossover(bool deserializing) : base(deserializing) { }
+    protected MultiLinearLinkageCrossover(MultiLinearLinkageCrossover original, Cloner cloner) : base(original, cloner) { }
+    public MultiLinearLinkageCrossover()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<LinearLinkage>("Parents", "The parent LLE which should be crossed."));
+      ParentsParameter.ActualName = "LLE";
+      Parameters.Add(new LookupParameter<LinearLinkage>("Child", "The child LLE resulting from the crossover."));
+      ChildParameter.ActualName = "LLE";
+
+      foreach (Type type in ApplicationManager.Manager.GetTypes(typeof(ILinearLinkageCrossover), typeof(LinearLinkageEncoding).Assembly)) {
+        if (!typeof(MultiOperator<ILinearLinkageCrossover>).IsAssignableFrom(type))
+          Operators.Add((ILinearLinkageCrossover)Activator.CreateInstance(type), true);
+      }
+
+      SelectedOperatorParameter.ActualName = "SelectedCrossoverOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiLinearLinkageCrossover(this, cloner);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<ILinearLinkageCrossover>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeCrossovers(e.Items);
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<ILinearLinkageCrossover>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeCrossovers(e.Items);
+    }
+
+    private void ParameterizeCrossovers(IEnumerable<IndexedItem<ILinearLinkageCrossover>> crossovers) {
+      foreach (var c in crossovers.Select(x => x.Value)) {
+        c.ChildParameter.ActualName = ChildParameter.Name;
+        c.ParentsParameter.ActualName = ParentsParameter.Name;
+        var stOp = c as IStochasticOperator;
+        if (stOp != null) stOp.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one LLE crossover to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/SinglePointCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/SinglePointCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Crossovers/SinglePointCrossover.cs	(revision 14663)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Single Point Crossover", "The single point crossover concatenates two linkage strings at a randomly chosen point.")]
+  [StorableClass]
+  public sealed class SinglePointCrossover : LinearLinkageCrossover {
+
+    [StorableConstructor]
+    private SinglePointCrossover(bool deserializing) : base(deserializing) { }
+    private SinglePointCrossover(SinglePointCrossover original, Cloner cloner) : base(original, cloner) { }
+    public SinglePointCrossover() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SinglePointCrossover(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) {
+      var length = p1.Length;
+      var child = LinearLinkage.SingleElementGroups(length);
+      var bp = random.Next(length - 1);
+      for (var i = 0; i <= bp; i++) child[i] = p1[i];
+      for (var i = bp + 1; i < length; i++) child[i] = p2[i];
+      child.LinearizeTreeStructures();
+      return child;
+    }
+
+    protected override LinearLinkage Cross(IRandom random, ItemArray<LinearLinkage> parents) {
+      if (parents.Length != 2) throw new InvalidOperationException(Name + ": Can only cross exactly two parents.");
+      return Apply(random, parents[0], parents[1]);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj	(revision 14663)
@@ -0,0 +1,229 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{BE698769-975A-429E-828C-72BB2B6182C8}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Encodings.LinearLinkageEncoding</RootNamespace>
+    <AssemblyName>HeuristicLab.Encodings.LinearLinkageEncoding-3.4</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <DocumentationFile>
+    </DocumentationFile>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
+      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
+      <Name>HeuristicLab.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
+      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
+      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
+      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
+      <Name>HeuristicLab.Parameters-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
+      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
+      <Name>HeuristicLab.Persistence-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{f4539fb6-4708-40c9-be64-0a1390aea197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Creators\ExactGroupsLinearLinkageCreator.cs" />
+    <Compile Include="Creators\MaxGroupSizeLinearLinkageCreator.cs" />
+    <Compile Include="Creators\MaxGroupsLinearLinkageCreator.cs" />
+    <Compile Include="Creators\RandomLinearLinkageCreator.cs" />
+    <Compile Include="Crossovers\GreedyPartitionCrossover.cs" />
+    <Compile Include="Crossovers\GroupCrossover.cs" />
+    <Compile Include="Crossovers\LowestIndexMaxCrossover.cs" />
+    <Compile Include="Crossovers\MultiLLECrossover.cs" />
+    <Compile Include="Crossovers\SinglePointCrossover.cs" />
+    <Compile Include="Interfaces\ILinearLinkageMoveOperator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageSwap2MoveOperator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageCreator.cs" />
+    <Compile Include="LinearLinkage.cs" />
+    <Compile Include="LinearLinkageCreator.cs" />
+    <Compile Include="LinearLinkageEncoding.cs" />
+    <Compile Include="LinearLinkageEqualityComparer.cs" />
+    <Compile Include="LinearLinkageManipulator.cs" />
+    <Compile Include="LinearLinkageCrossover.cs" />
+    <Compile Include="Manipulators\GraftManipulator.cs" />
+    <Compile Include="Manipulators\MoveItemManipulator.cs" />
+    <Compile Include="Manipulators\MergeGroupManipulator.cs" />
+    <Compile Include="Manipulators\MultiLLEManipulator.cs" />
+    <Compile Include="Moves\ExtractMove.cs" />
+    <Compile Include="Moves\MergeMove.cs" />
+    <Compile Include="Moves\Move.cs" />
+    <Compile Include="Moves\ShiftMove.cs" />
+    <Compile Include="Moves\SplitMove.cs" />
+    <Compile Include="Moves\StaticAPI\MoveGenerator.cs" />
+    <Compile Include="Moves\Swap\ExhaustiveSwap2MoveGenerator.cs" />
+    <Compile Include="Moves\Swap\StochasticSwap2MultiMoveGenerator.cs" />
+    <Compile Include="Moves\Swap\StochasticSwap2SingleMoveGenerator.cs" />
+    <Compile Include="Moves\Swap\Swap2Move.cs" />
+    <Compile Include="Moves\Swap\Swap2MoveGenerator.cs" />
+    <Compile Include="Moves\Swap\Swap2MoveMaker.cs" />
+    <Compile Include="ShakingOperators\LLEShakingOperator.cs" />
+    <Compile Include="SimilarityCalculators\HammingSimilarityCalculator.cs" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="Crossovers\LowestIndexFirstCrossover.cs" />
+    <Compile Include="Interfaces\ILinearLinkageCrossover.cs" />
+    <Compile Include="Interfaces\ILinearLinkageManipulator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageOperator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageShakingOperator.cs" />
+    <Compile Include="Manipulators\SplitGroupManipulator.cs" />
+    <Compile Include="Manipulators\SwapItemManipulator.cs" />
+    <Compile Include="Plugin.cs" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+    </PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+    </PreBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageCreator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageCreator.cs	(revision 14663)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public interface ILinearLinkageCreator : ISolutionCreator, ILinearLinkageOperator {
+    IValueLookupParameter<IntValue> LengthParameter { get; }
+    ILookupParameter<LinearLinkage> LLEParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageCrossover.cs	(revision 14663)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public interface ILinearLinkageCrossover : ICrossover, ILinearLinkageOperator {
+    ILookupParameter<LinearLinkage> ChildParameter { get; }
+    IScopeTreeLookupParameter<LinearLinkage> ParentsParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageManipulator.cs	(revision 14663)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public interface ILinearLinkageManipulator : IManipulator, ILinearLinkageOperator {
+    ILookupParameter<LinearLinkage> LLEParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageMoveOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageMoveOperator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageMoveOperator.cs	(revision 14663)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  /// <summary>
+  /// Move operators can be extended by deriving a new interface from this interface
+  /// and implementing that derived interface in all move operators that belong to
+  /// the same group of move operators.
+  /// 
+  /// See <see cref="ILinearLinkageSwap2MoveOperator"/> for a reference implementation.
+  /// </summary>
+  public interface ILinearLinkageMoveOperator : IMoveOperator, ILinearLinkageOperator {
+    ILookupParameter<LinearLinkage> LLEParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageOperator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageOperator.cs	(revision 14663)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public interface ILinearLinkageOperator : IOperator {
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageShakingOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageShakingOperator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageShakingOperator.cs	(revision 14663)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public interface ILinearLinkageShakingOperator : ILinearLinkageOperator {
+    ILookupParameter<LinearLinkage> LLEParameter { get; }
+    ICheckedItemList<ILinearLinkageManipulator> Shakers { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageSwap2MoveOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageSwap2MoveOperator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Interfaces/ILinearLinkageSwap2MoveOperator.cs	(revision 14663)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public interface ILinearLinkageSwap2MoveOperator : ILinearLinkageMoveOperator {
+    ILookupParameter<Swap2Move> Swap2MoveParameter { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkage.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkage.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkage.cs	(revision 14663)
@@ -0,0 +1,409 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("LinearLinkage", "Represents an LLE grouping of items.")]
+  [StorableClass]
+  public sealed class LinearLinkage : IntArray {
+
+    [StorableConstructor]
+    private LinearLinkage(bool deserializing) : base(deserializing) { }
+    private LinearLinkage(LinearLinkage original, Cloner cloner) : base(original, cloner) { }
+    public LinearLinkage() { }
+
+    private LinearLinkage(int length) : base(length) { }
+    private LinearLinkage(int[] elements) : base(elements) { }
+
+    /// <summary>
+    /// Create a new LinearLinkage object where every element is in a seperate group.
+    /// </summary>
+    public static LinearLinkage SingleElementGroups(int length) {
+      var elements = new int[length];
+      for (var i = 0; i < length; i++) {
+        elements[i] = i;
+      }
+      return new LinearLinkage(elements);
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object from an int[] in LLE
+    /// </summary>
+    /// <remarks>
+    /// This operation checks if the argument is a well formed LLE
+    /// and throws an ArgumentException otherwise.
+    /// </remarks>
+    /// <exception cref="ArgumentException">If <paramref name="lle"/> does not represent a valid LLE array.</exception>
+    /// <param name="lle">The LLE representation</param>
+    /// <returns>The linear linkage encoding in LLE format (with forward-links).</returns>
+    public static LinearLinkage FromForwardLinks(int[] lle) {
+      if (!Validate(lle))
+        throw new ArgumentException("Array is malformed and does not represent a valid LLE forward encoding.", "elements");
+      return new LinearLinkage(lle);
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object by parsing a LLE-b representation
+    /// and modifing the underlying array so that it is in LLE representation.
+    /// </summary>
+    /// <remarks>
+    /// This operation runs in O(n) time, the parameter <paramref name="lleb"/> is not modified.
+    /// </remarks>
+    /// <exception cref="ArgumentException">If <paramref name="lleb"/> does not represent a valid LLE-b array.</exception>
+    /// <param name="lleb">The LLE-b representation (LLE with back-links)</param>
+    /// <returns>The linear linkage encoding in LLE format (with forward-links).</returns>
+    public static LinearLinkage FromBackLinks(int[] lleb) {
+      var result = new LinearLinkage(lleb.Length);
+      for (var i = lleb.Length - 1; i > 0; i--) {
+        if (lleb[i] == i) {
+          if (result[i] == 0) result[i] = i;
+          continue;
+        }
+        result[lleb[i]] = i;
+        if (result[i] == 0) result[i] = i;
+      }
+      if (!Validate(result.array))
+        throw new ArgumentException("Array is malformed and does not represent a valid LLE-b encoding (with back-links).", "lleb");
+      return result;
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object by parsing an LLE-e representation
+    /// and modifing the underlying array so that it is in LLE representation.
+    /// </summary>
+    /// <remarks>
+    /// This operation runs in O(n) time, but requires additional memory
+    /// in form of a int[].
+    /// </remarks>
+    /// <param name="llee">The LLE-e representation</param>
+    /// <returns>The linear linkage encoding in LLE format (with forward-links).</returns>
+    public static LinearLinkage FromEndLinks(int[] llee) {
+      var result = new LinearLinkage(llee.Length);
+      result.SetEndLinks(llee);
+      return result;
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object by translating
+    /// an enumeration of groups into the underlying array representation.
+    /// </summary>
+    /// <remarks>
+    /// Throws an ArgumentException when there is an element assigned to
+    /// multiple groups or elements that are not assigned to any group.
+    /// </remarks>
+    /// <param name="grouping">The grouping of the elements, each element must
+    /// be part of exactly one group.</param>
+    public static LinearLinkage FromGroups(int length, IEnumerable<IEnumerable<int>> grouping) {
+      var result = new LinearLinkage(length);
+      result.SetGroups(grouping);
+      return result;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LinearLinkage(this, cloner);
+    }
+
+    /// <summary>
+    /// This method parses the encoded array and calculates the membership of
+    /// each element to the groups. It starts at the lowest element.
+    /// </summary>
+    /// <remarks>
+    /// Runtime complexity of this method is O(n) where n is the length of the
+    /// array.
+    /// </remarks>
+    /// <exception cref="InvalidOperationException">If this object is not vaild LLE.</exception>
+    /// <returns>An enumeration of all groups.</returns>
+    public IEnumerable<List<int>> GetGroups() {
+      var len = array.Length;
+      var used = new bool[len];
+      for (var i = 0; i < len; i++) {
+        if (used[i]) continue;
+        var curr = i;
+        var next = array[curr];
+        var group = new List<int> { curr };
+        while (next > curr && next < len && !used[next]) {
+          used[curr] = true;
+          curr = next;
+          next = array[next];
+          group.Add(curr);
+        }
+        if (curr != next) throw new InvalidOperationException("Array is malformed and does not represent a valid LLE forward encoding.");
+        used[curr] = true;
+        yield return group;
+      }
+    }
+
+    /// <summary>
+    /// This method parses the encoded array and gathers all elements
+    /// that belong to the same group as element <paramref name="index"/>.
+    /// </summary>
+    /// <param name="index">The element whose group should be returned.
+    /// </param>
+    /// <returns>The element at <paramref name="index"/> and all other
+    /// elements in the same group.</returns>
+    public IEnumerable<int> GetGroup(int index) {
+      foreach (var n in GetGroupForward(index))
+        yield return n;
+      // the element index has already been yielded
+      foreach (var n in GetGroupBackward(index).Skip(1))
+        yield return n;
+    }
+
+    /// <summary>
+    /// This method parses the encoded array and gathers the element
+    /// <paramref name="index"/> as well as subsequent elements that
+    /// belong to the same group.
+    /// </summary>
+    /// <param name="index">The element from which subsequent (having a
+    /// larger number) elements in the group should be returned.
+    /// </param>
+    /// <returns>The element <paramref name="index"/> and all subsequent
+    /// elements in the same group.</returns>
+    public IEnumerable<int> GetGroupForward(int index) {
+      yield return index;
+      var next = array[index];
+      if (next == index) yield break;
+      int prev;
+      do {
+        yield return next;
+        prev = next;
+        next = array[next];
+      } while (next != prev);
+    }
+
+    /// <summary>
+    /// This method parses the encoded array and gathers the element
+    /// given <paramref name="index"/> as well as preceeding elements that
+    /// belong to the same group.
+    /// </summary>
+    /// <remarks>
+    /// Warning, this code has performance O(index) as the array has to
+    /// be fully traversed backwards from the given index.
+    /// </remarks>
+    /// <param name="index">The element from which preceeding (having a
+    /// smaller number) elements in the group should be returned.
+    /// </param>
+    /// <returns>The element <paramref name="index"/> and all preceeding
+    /// elements in the same group.</returns>
+    public IEnumerable<int> GetGroupBackward(int index) {
+      yield return index;
+      var next = array[index];
+      // return preceding elements in group
+      for (var prev = index - 1; prev >= 0; prev--) {
+        if (array[prev] != next) continue;
+        next = prev;
+        yield return next;
+      }
+    }
+
+    /// <summary>
+    /// This method translates an enumeration of groups into the underlying
+    /// array representation.
+    /// </summary>
+    /// <remarks>
+    /// Throws an ArgumentException when there is an element assigned to
+    /// multiple groups or elements that are not assigned to any group.
+    /// </remarks>
+    /// <param name="grouping">The grouping of the elements, each element must
+    /// be part of exactly one group.</param>
+    /// <exception cref="ArgumentException">If <paramref name="grouping"/> cannot be converted
+    /// to a valid LLE representation. For instance, because elements are too big or too small,
+    /// or they're contained in multiple groups, or there are elements not assigned to any group.
+    /// </exception>
+    public void SetGroups(IEnumerable<IEnumerable<int>> grouping) {
+      var len = array.Length;
+      var used = new bool[len];
+      foreach (var group in grouping) {
+        var prev = -1;
+        foreach (var g in group.OrderBy(x => x)) {
+          if (g < prev || g >= len) throw new ArgumentException(string.Format("Element {0} is bigger than {1} or smaller than 0.", g, len - 1), "grouping");
+          if (prev >= 0) array[prev] = g;
+          prev = g;
+          if (used[prev]) {
+            throw new ArgumentException(string.Format("Element {0} is contained at least twice.", prev), "grouping");
+          }
+          used[prev] = true;
+        }
+        array[prev] = prev;
+      }
+      if (!used.All(x => x))
+        throw new ArgumentException(string.Format("Elements are not assigned a group: {0}", string.Join(", ", used.Select((x, i) => new { x, i }).Where(x => !x.x).Select(x => x.i))));
+    }
+
+    /// <summary>
+    /// Performs a check whether the array represents a valid LLE encoding.
+    /// </summary>
+    /// <remarks>
+    /// The runtime complexity of this method is O(n) where n is the length of
+    /// the array.
+    /// </remarks>
+    /// <returns>True if the encoding is valid.</returns>
+    public bool Validate() {
+      return Validate(array);
+    }
+
+    private static bool Validate(int[] array) {
+      var len = array.Length;
+      var used = new bool[len];
+      for (var i = 0; i < len; i++) {
+        if (used[i]) continue;
+        var curr = i;
+        var next = array[curr];
+        while (next > curr && next < len && !used[next]) {
+          used[curr] = true;
+          curr = next;
+          next = array[next];
+        }
+        if (curr != next) return false;
+        used[curr] = true;
+      }
+      return true;
+    }
+
+    /// <summary>
+    /// This method flattens tree structures that may be present in groups.
+    /// These tree structures may be created by e.g. merging two groups by
+    /// linking one end node to the end node of another.
+    /// Consider following array: 5, 5, 6, 4, 4, 7, 7, 7, 8.
+    /// This results in the following tree structure for group 7:
+    ///      7
+    ///    /   \
+    ///   5     6
+    ///  / \    |
+    /// 0   1   2
+    /// After this operation the array will be 1, 2, 5, 4, 4, 6, 7, 7, 8.
+    /// Representing a tree with one branch: 0 -> 1 -> 2 -> 5 -> 6 -> 7.
+    /// </summary>
+    /// <remarks>
+    /// The method first converts the array to LLE-e format and then
+    /// linearizes the links. This requires two passes of the whole array
+    /// as well as another copy of the underlying array.
+    /// The runtime complexity is O(n).
+    /// 
+    /// The method assumes that there are no back links present.
+    /// </remarks>
+    public void LinearizeTreeStructures() {
+      // Step 1: Convert the array into LLE-e
+      ToEndLinksInplace(array);
+      // Step 2: For all groups linearize the links
+      SetEndLinks(array);
+    }
+
+    /// <summary>
+    /// Creates a copy of the underlying array and turns it into LLE-e.
+    /// </summary>
+    /// <remarks>
+    /// LLE-e is a special format where each element points to the
+    /// ending item of a group.
+    /// The LLE representation 1, 2, 4, 5, 4, 6, 7, 7 would become 
+    /// 4, 4, 4, 7, 4, 7, 7, 7 in LLE-e.
+    /// 
+    /// This operation runs in O(n) time.
+    /// </remarks>
+    /// <exception cref="ArgumentException">In case, this object does not
+    /// represent a valid LLE encoding.
+    /// </exception>
+    /// <returns>An integer array in LLE-e representation</returns>
+    public int[] ToEndLinks() {
+      var result = (int[])array.Clone();
+      ToEndLinksInplace(result);
+      return result;
+    }
+
+    private static void ToEndLinksInplace(int[] array) {
+      var length = array.Length;
+      for (var i = length - 1; i >= 0; i--) {
+        var next = array[i];
+        if (next > i) {
+          array[i] = array[next];
+        } else if (next < i) {
+          throw new ArgumentException("Array is malformed and does not represent a valid LLE encoding.", "array");
+        }
+      }
+    }
+
+    /// <summary>
+    /// Parses an LLE-e representation and modifies the underlying array
+    /// so that it is in LLE representation.
+    /// </summary>
+    /// <remarks>
+    /// This operation runs in O(n) time, but requires additional memory
+    /// in form of a int[].
+    /// </remarks>
+    /// <param name="llee">The LLE-e representation</param>
+    /// <exception cref="ArgumentException">
+    /// If <paramref name="llee"/> does not contain a valid LLE-e representation or
+    /// has a different length to the given instance.
+    /// </exception>
+    public void SetEndLinks(int[] llee) {
+      var length = array.Length;
+      if (length != llee.Length) {
+        throw new ArgumentException(string.Format("Expected length {0} but length was {1}", length, llee.Length), "llee");
+      }
+      // If we are ok with mutating llee we can avoid this clone
+      var lookup = (int[])llee.Clone();
+      for (var i = length - 1; i >= 0; i--) {
+        var end = llee[i];
+        if (end == i) {
+          array[i] = end;
+        } else if (end > i && end < length) {
+          array[i] = lookup[end];
+          lookup[end] = i;
+        } else {
+          throw new ArgumentException("Array is malformed and does not represent a valid LLE-e end encoding.", "llee");
+        }
+      }
+    }
+
+    /// <summary>
+    /// Creates a copy of the underlying array and turns it into LLE-b.
+    /// </summary>
+    /// <remarks>
+    /// LLE-b is a special format where each element points to the
+    /// predecessor instead of the successor.
+    /// The LLE representation 1, 2, 4, 5, 4, 6, 7, 7
+    /// would become           0, 0, 1, 3, 2, 3, 5, 6 in LLE-b.
+    /// 
+    /// This operation runs in O(n) time.
+    /// </remarks>
+    /// <returns>An integer array in LLE-b representation</returns>
+    public int[] ToBackLinks() {
+      var result = new int[array.Length];
+      var zeroLink = array[0];
+      for (var i = 0; i < array.Length; i++) {
+        if (array[i] == i) {
+          if (result[i] == 0 && i != zeroLink) result[i] = i;
+          continue;
+        }
+        result[array[i]] = i;
+        if (result[i] == 0 && i != zeroLink) result[i] = i;
+      }
+      return result;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageCreator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageCreator.cs	(revision 14663)
@@ -0,0 +1,64 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Linear Linkage Creator", "Base class for linear linkage creators.")]
+  [StorableClass]
+  public abstract class LinearLinkageCreator : InstrumentedOperator, ILinearLinkageCreator, IStochasticOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<LinearLinkage> LLEParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["LLE"]; }
+    }
+
+    public IValueLookupParameter<IntValue> LengthParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["Length"]; }
+    }
+
+    [StorableConstructor]
+    protected LinearLinkageCreator(bool deserializing) : base(deserializing) { }
+    protected LinearLinkageCreator(LinearLinkageCreator original, Cloner cloner) : base(original, cloner) { }
+    protected LinearLinkageCreator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<LinearLinkage>("LLE", "The encoding vector that is to be created.") { Hidden = false });
+      Parameters.Add(new ValueLookupParameter<IntValue>("Length", "The length of the vector that is to be created."));
+    }
+
+    public override IOperation InstrumentedApply() {
+      var random = RandomParameter.ActualValue;
+      LLEParameter.ActualValue = Create(random, LengthParameter.ActualValue.Value);
+      return base.InstrumentedApply();
+    }
+
+    protected abstract LinearLinkage Create(IRandom random, int length);
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageCrossover.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageCrossover.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageCrossover.cs	(revision 14663)
@@ -0,0 +1,67 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Linear Linkage Crossover", "Base class for linear linkage crossovers.")]
+  [StorableClass]
+  public abstract class LinearLinkageCrossover : InstrumentedOperator, ILinearLinkageCrossover, IStochasticOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<LinearLinkage> ChildParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["Child"]; }
+    }
+
+    public IScopeTreeLookupParameter<LinearLinkage> ParentsParameter {
+      get { return (IScopeTreeLookupParameter<LinearLinkage>)Parameters["Parents"]; }
+    }
+
+    [StorableConstructor]
+    protected LinearLinkageCrossover(bool deserializing) : base(deserializing) { }
+    protected LinearLinkageCrossover(LinearLinkageCrossover original, Cloner cloner) : base(original, cloner) { }
+    protected LinearLinkageCrossover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<LinearLinkage>("Child", "The child that is to be created."));
+      Parameters.Add(new ScopeTreeLookupParameter<LinearLinkage>("Parents", "The parents that are to be crossed."));
+    }
+
+    public override IOperation InstrumentedApply() {
+      var random = RandomParameter.ActualValue;
+      var parents = ParentsParameter.ActualValue;
+      if (parents == null) throw new InvalidOperationException(Name + ": Parents could not be found.");
+      var child = Cross(random, parents);
+      ChildParameter.ActualValue = child;
+      return base.InstrumentedApply();
+    }
+
+    protected abstract LinearLinkage Cross(IRandom random, ItemArray<LinearLinkage> parents);
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageEncoding.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageEncoding.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageEncoding.cs	(revision 14663)
@@ -0,0 +1,179 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Linear Linkage Encoding", "Describes a linear linkage (LLE) encoding.")]
+  [StorableClass]
+  public sealed class LinearLinkageEncoding : Encoding<ILinearLinkageCreator> {
+    #region encoding parameters
+    [Storable]
+    private IFixedValueParameter<IntValue> lengthParameter;
+    public IFixedValueParameter<IntValue> LengthParameter {
+      get { return lengthParameter; }
+      set {
+        if (value == null) throw new ArgumentNullException("Length parameter must not be null.");
+        if (value.Value == null) throw new ArgumentNullException("Length parameter value must not be null.");
+        if (lengthParameter == value) return;
+
+        if (lengthParameter != null) Parameters.Remove(lengthParameter);
+        lengthParameter = value;
+        Parameters.Add(lengthParameter);
+        OnLengthParameterChanged();
+      }
+    }
+    #endregion
+
+    public int Length {
+      get { return LengthParameter.Value.Value; }
+      set { LengthParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private LinearLinkageEncoding(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterParameterEvents();
+      DiscoverOperators();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) { return new LinearLinkageEncoding(this, cloner); }
+    private LinearLinkageEncoding(LinearLinkageEncoding original, Cloner cloner)
+      : base(original, cloner) {
+      lengthParameter = cloner.Clone(original.lengthParameter);
+      RegisterParameterEvents();
+    }
+
+
+    public LinearLinkageEncoding() : this("LLE", 10) { }
+    public LinearLinkageEncoding(string name) : this(name, 10) { }
+    public LinearLinkageEncoding(int length) : this("LLE", length) { }
+    public LinearLinkageEncoding(string name, int length)
+      : base(name) {
+      lengthParameter = new FixedValueParameter<IntValue>(Name + ".Length", new IntValue(length));
+      Parameters.Add(lengthParameter);
+
+      SolutionCreator = new RandomLinearLinkageCreator();
+      RegisterParameterEvents();
+      DiscoverOperators();
+    }
+
+    private void OnLengthParameterChanged() {
+      RegisterLengthParameterEvents();
+      ConfigureOperators(Operators);
+    }
+
+    private void RegisterParameterEvents() {
+      RegisterLengthParameterEvents();
+    }
+    private void RegisterLengthParameterEvents() {
+      LengthParameter.Value.ValueChanged += (o, s) => ConfigureOperators(Operators);
+    }
+
+    #region Operator Discovery
+    private static readonly IEnumerable<Type> encodingSpecificOperatorTypes;
+    static LinearLinkageEncoding() {
+      encodingSpecificOperatorTypes = new List<Type>() {
+          typeof (ILinearLinkageOperator),
+          typeof (ILinearLinkageCreator),
+          typeof (ILinearLinkageCrossover),
+          typeof (ILinearLinkageManipulator),
+          typeof (ILinearLinkageShakingOperator),
+          typeof (ILinearLinkageMoveOperator)
+      };
+    }
+    private void DiscoverOperators() {
+      var assembly = typeof(ILinearLinkageOperator).Assembly;
+      var discoveredTypes = ApplicationManager.Manager.GetTypes(encodingSpecificOperatorTypes, assembly, true, false, false);
+      var operators = discoveredTypes.Select(t => (IOperator)Activator.CreateInstance(t));
+      var newOperators = operators.Except(Operators, new TypeEqualityComparer<IOperator>()).ToList();
+
+      ConfigureOperators(newOperators);
+      foreach (var @operator in newOperators)
+        AddOperator(@operator);
+    }
+    #endregion
+
+    public override void ConfigureOperators(IEnumerable<IOperator> operators) {
+      ConfigureCreators(operators.OfType<ILinearLinkageCreator>());
+      ConfigureCrossovers(operators.OfType<ILinearLinkageCrossover>());
+      ConfigureManipulators(operators.OfType<ILinearLinkageManipulator>());
+      ConfigureShakingOperators(operators.OfType<ILinearLinkageShakingOperator>());
+      ConfigureMoveOperators(operators.OfType<ILinearLinkageMoveOperator>());
+      ConfigureSwap2MoveOperators(operators.OfType<ILinearLinkageSwap2MoveOperator>());
+    }
+
+    #region specific operator wiring
+    private void ConfigureCreators(IEnumerable<ILinearLinkageCreator> creators) {
+      foreach (var creator in creators) {
+        creator.LengthParameter.ActualName = LengthParameter.Name;
+        creator.LLEParameter.ActualName = Name;
+      }
+    }
+    private void ConfigureCrossovers(IEnumerable<ILinearLinkageCrossover> crossovers) {
+      foreach (var crossover in crossovers) {
+        crossover.ChildParameter.ActualName = Name;
+        crossover.ParentsParameter.ActualName = Name;
+      }
+    }
+    private void ConfigureManipulators(IEnumerable<ILinearLinkageManipulator> manipulators) {
+      foreach (var manipulator in manipulators) {
+        manipulator.LLEParameter.ActualName = Name;
+      }
+    }
+    private void ConfigureShakingOperators(IEnumerable<ILinearLinkageShakingOperator> shakingOperators) {
+      foreach (var shakingOperator in shakingOperators) {
+        shakingOperator.LLEParameter.ActualName = Name;
+      }
+    }
+    private void ConfigureMoveOperators(IEnumerable<ILinearLinkageMoveOperator> moveOperators) {
+      foreach (var moveOperator in moveOperators) {
+        moveOperator.LLEParameter.ActualName = Name;
+      }
+    }
+    private void ConfigureSwap2MoveOperators(IEnumerable<ILinearLinkageSwap2MoveOperator> swap2MoveOperators) {
+      foreach (var swap2MoveOperator in swap2MoveOperators) {
+        swap2MoveOperator.Swap2MoveParameter.ActualName = Name + ".Swap2Move";
+      }
+    }
+    #endregion
+  }
+
+  public static class IndividualExtensionMethods {
+    public static LinearLinkage LinearLinkage(this Individual individual) {
+      var encoding = individual.GetEncoding<LinearLinkageEncoding>();
+      return individual.LinearLinkage(encoding.Name);
+    }
+    public static LinearLinkage LinearLinkage(this Individual individual, string name) {
+      return (LinearLinkage)individual[name];
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageEqualityComparer.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageEqualityComparer.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageEqualityComparer.cs	(revision 14663)
@@ -0,0 +1,44 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Collections.Generic;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public class LinearLinkageEqualityComparer : EqualityComparer<LinearLinkage> {
+    public override bool Equals(LinearLinkage x, LinearLinkage y) {
+      if (x == null && y == null) return true;
+      if (x == null || y == null) return false;
+      if (x.Length != y.Length) return false;
+      for (var i = 0; i < x.Length; i++)
+        if (x[i] != y[i]) return false;
+      return true;
+    }
+
+    public override int GetHashCode(LinearLinkage obj) {
+      unchecked {
+        int hash = 17;
+        foreach (var o in obj)
+          hash = hash * 31 + o.GetHashCode();
+        return hash;
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/LinearLinkageManipulator.cs	(revision 14663)
@@ -0,0 +1,58 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Linear Linkage Manipulator", "Base class for linear linkage manipulators.")]
+  [StorableClass]
+  public abstract class LinearLinkageManipulator : InstrumentedOperator, ILinearLinkageManipulator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<LinearLinkage> LLEParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["LLE"]; }
+    }
+
+    [StorableConstructor]
+    protected LinearLinkageManipulator(bool deserializing) : base(deserializing) { }
+    protected LinearLinkageManipulator(LinearLinkageManipulator original, Cloner cloner) : base(original, cloner) { }
+    protected LinearLinkageManipulator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<LinearLinkage>("LLE", "The encoding vector that is to be manipulated."));
+    }
+
+    public override IOperation InstrumentedApply() {
+      var random = RandomParameter.ActualValue;
+      var lle = LLEParameter.ActualValue;
+      Manipulate(random, lle);
+      return base.InstrumentedApply();
+    }
+
+    protected abstract void Manipulate(IRandom random, LinearLinkage lle);
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/GraftManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/GraftManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/GraftManipulator.cs	(revision 14663)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Graft Manipulator", "Performs graft mutation as described in Du, J., Korkmaz, E.E., Alhajj, R., and Barker, K. 2004. Novel Clustering Approach that employs Genetic Algorithm with New Representation Scheme and Multiple Objectives. Data Warehousing and Knowledge Discovery, pp. 219-228. Springer Berlin Heidelberg.")]
+  [StorableClass]
+  public sealed class GraftManipulator : LinearLinkageManipulator {
+
+    [StorableConstructor]
+    private GraftManipulator(bool deserializing) : base(deserializing) { }
+    private GraftManipulator(GraftManipulator original, Cloner cloner) : base(original, cloner) { }
+    public GraftManipulator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GraftManipulator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, LinearLinkage lle) {
+      int tries = lle.Length;
+      var index = random.Next(lle.Length);
+      while (tries > 0 && lle[index] == index) {
+        index = random.Next(lle.Length);
+        tries--;
+      }
+      if (lle[index] != index) Apply(random, lle, index);
+    }
+
+    public static void Apply(IRandom random, LinearLinkage lle, int index) {
+      var groups = lle.Select((val, idx) => Tuple.Create(idx, val))
+                      .Where(x => x.Item1 == x.Item2)
+                      .Select(x => x.Item2).ToList();
+      var z = groups.Count;
+
+      if (random.NextDouble() < 0.5)
+        lle[index] = index; // divide the cluster into two
+      else {
+        var c = random.Next(z);
+        if (groups[c] > index)
+          lle[index] = groups[c]; // combine the portion with another class
+        else {
+          // combine the other class here
+          lle[groups[c]] = lle[index];
+          lle[index] = index;
+        }
+        lle.LinearizeTreeStructures();
+      }
+    }
+
+    protected override void Manipulate(IRandom random, LinearLinkage lle) {
+      Apply(random, lle);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MergeGroupManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MergeGroupManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MergeGroupManipulator.cs	(revision 14663)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Merge Group Manipulator", "Performs a maximum of N merge operations on the groups. An already merged group may be merged again.")]
+  [StorableClass]
+  public sealed class MergeGroupManipulator : LinearLinkageManipulator {
+
+    public IValueLookupParameter<IntValue> NParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["N"]; }
+    }
+
+    [StorableConstructor]
+    private MergeGroupManipulator(bool deserializing) : base(deserializing) { }
+    private MergeGroupManipulator(MergeGroupManipulator original, Cloner cloner) : base(original, cloner) { }
+    public MergeGroupManipulator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("N", "The number of groups to merge.", new IntValue(1)));
+    }
+    public MergeGroupManipulator(int n)
+      : this() {
+      NParameter.Value = new IntValue(n);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MergeGroupManipulator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, LinearLinkage lle, int n) {
+      var grouping = lle.GetGroups().ToList();
+      if (grouping.Count == 1) return; // nothing to merge
+
+      for (var i = 0; i < n; i++) {
+        var g1 = random.Next(grouping.Count);
+        var g2 = random.Next(grouping.Count);
+        while (g1 == g2) g2 = random.Next(grouping.Count);
+        grouping[g1].AddRange(grouping[g2]);
+        grouping.RemoveAt(g2);
+        if (grouping.Count == 1) break;
+      }
+
+      lle.SetGroups(grouping);
+    }
+
+    protected override void Manipulate(IRandom random, LinearLinkage lle) {
+      var N = NParameter.ActualValue.Value;
+      Apply(random, lle, N);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MoveItemManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MoveItemManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MoveItemManipulator.cs	(revision 14663)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Move Item Manipulator", "Performs a maximum of N move operations between groups or to new groups. An already moved item may be moved again.")]
+  [StorableClass]
+  public sealed class MoveItemManipulator : LinearLinkageManipulator {
+
+    public IValueLookupParameter<IntValue> NParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["N"]; }
+    }
+
+    [StorableConstructor]
+    private MoveItemManipulator(bool deserializing) : base(deserializing) { }
+    private MoveItemManipulator(MoveItemManipulator original, Cloner cloner) : base(original, cloner) { }
+    public MoveItemManipulator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("N", "The number of items to move.", new IntValue(1)));
+    }
+    public MoveItemManipulator(int n)
+      : this() {
+      NParameter.Value = new IntValue(n);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MoveItemManipulator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, LinearLinkage lle, int n) {
+      var grouping = lle.GetGroups().ToList();
+      grouping.Add(new List<int>()); // add an empty group
+
+      for (var i = 0; i < n; i++) {
+        var src = random.Next(grouping.Count - 1); // only select from non-empty groups
+        var dest = random.Next(grouping.Count);
+        while (src == dest || grouping[src].Count == 1 && dest == grouping.Count - 1) {
+          src = random.Next(grouping.Count - 1);
+          dest = random.Next(grouping.Count);
+        }
+        if (dest == grouping.Count - 1) grouping.Add(new List<int>());
+
+        var e = random.Next(grouping[src].Count);
+        grouping[dest].Add(grouping[src][e]);
+        grouping[src].RemoveAt(e);
+        if (grouping[src].Count == 0)
+          grouping.RemoveAt(src);
+      }
+
+      lle.SetGroups(grouping.Where(x => x.Count > 0));
+    }
+
+    protected override void Manipulate(IRandom random, LinearLinkage lle) {
+      var N = NParameter.ActualValue.Value;
+      Apply(random, lle, N);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MultiLLEManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MultiLLEManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/MultiLLEManipulator.cs	(revision 14663)
@@ -0,0 +1,90 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Reflection;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Multi LLE Manipulator", "Randomly selects and applies one of its manipulators every time it is called.")]
+  [StorableClass]
+  public class MultiLinearLinkageManipulator : StochasticMultiBranch<ILinearLinkageManipulator>, ILinearLinkageManipulator, IStochasticOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    protected override bool CreateChildOperation {
+      get { return true; }
+    }
+
+    public ILookupParameter<LinearLinkage> LLEParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["LLE"]; }
+    }
+
+    [StorableConstructor]
+    protected MultiLinearLinkageManipulator(bool deserializing) : base(deserializing) { }
+    protected MultiLinearLinkageManipulator(MultiLinearLinkageManipulator original, Cloner cloner) : base(original, cloner) { }
+    public MultiLinearLinkageManipulator()
+      : base() {
+      Parameters.Add(new LookupParameter<LinearLinkage>("LLE", "The encoding vector that is to be manipulated."));
+      foreach (Type type in ApplicationManager.Manager.GetTypes(typeof(ILinearLinkageManipulator), typeof(LinearLinkageEncoding).Assembly)) {
+        if (!typeof(MultiOperator<ILinearLinkageManipulator>).IsAssignableFrom(type))
+          Operators.Add((ILinearLinkageManipulator)Activator.CreateInstance(type), true);
+      }
+      SelectedOperatorParameter.ActualName = "SelectedManipulationOperator";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiLinearLinkageManipulator(this, cloner);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<ILinearLinkageManipulator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeManipulators(e.Items);
+    }
+
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<ILinearLinkageManipulator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeManipulators(e.Items);
+    }
+
+    private void ParameterizeManipulators(IEnumerable<IndexedItem<ILinearLinkageManipulator>> manipulators) {
+      foreach (var m in manipulators.Select(x => x.Value)) {
+        m.LLEParameter.ActualName = LLEParameter.Name;
+        var stOp = m as IStochasticOperator;
+        if (stOp != null) stOp.RandomParameter.ActualName = RandomParameter.Name;
+      }
+    }
+
+    public override IOperation InstrumentedApply() {
+      if (Operators.Count == 0) throw new InvalidOperationException(Name + ": Please add at least one LLE manipulator to choose from.");
+      return base.InstrumentedApply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/SplitGroupManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/SplitGroupManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/SplitGroupManipulator.cs	(revision 14663)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Split Group Manipulator", "Performs a maximum of N split operations on the groups. An already split group may be split again.")]
+  [StorableClass]
+  public sealed class SplitGroupManipulator : LinearLinkageManipulator {
+
+    public IValueLookupParameter<IntValue> NParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["N"]; }
+    }
+
+    [StorableConstructor]
+    private SplitGroupManipulator(bool deserializing) : base(deserializing) { }
+    private SplitGroupManipulator(SplitGroupManipulator original, Cloner cloner) : base(original, cloner) { }
+    public SplitGroupManipulator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("N", "The number of groups to split.", new IntValue(1)));
+    }
+    public SplitGroupManipulator(int n)
+      : this() {
+      NParameter.Value = new IntValue(n);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SplitGroupManipulator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, LinearLinkage lle, int n) {
+      var grouping = lle.GetGroups().ToList();
+      var groupsLargerOne = grouping.Select((v, i) => Tuple.Create(i, v))
+                                    .Where(x => x.Item2.Count > 1)
+                                    .ToDictionary(x => x.Item1, x => x.Item2);
+      if (groupsLargerOne.Count == 0) return;
+      var toRemove = new List<int>();
+
+      for (var i = 0; i < n; i++) {
+        var g = groupsLargerOne.Keys.SampleRandom(random);
+        var idx = random.Next(1, groupsLargerOne[g].Count);
+        // shuffle here to avoid a potential bias of grouping smaller and larger numbers together
+        var tmp = groupsLargerOne[g].Shuffle(random);
+        var before = new List<int>();
+        var after = new List<int>();
+        foreach (var t in tmp) {
+          if (idx > 0) before.Add(t);
+          else after.Add(t);
+          idx--;
+        }
+        if (before.Count > 1) groupsLargerOne[grouping.Count] = before;
+        grouping.Add(before);
+        if (after.Count > 1) groupsLargerOne[grouping.Count] = after;
+        grouping.Add(after);
+        toRemove.Add(g);
+        groupsLargerOne.Remove(g);
+        if (groupsLargerOne.Count == 0) break;
+      }
+      foreach (var r in toRemove.OrderByDescending(x => x))
+        grouping.RemoveAt(r);
+
+      lle.SetGroups(grouping);
+    }
+
+    protected override void Manipulate(IRandom random, LinearLinkage lle) {
+      var N = NParameter.ActualValue.Value;
+      Apply(random, lle, N);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/SwapItemManipulator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/SwapItemManipulator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Manipulators/SwapItemManipulator.cs	(revision 14663)
@@ -0,0 +1,80 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Swap Item Manipulator", "Performs N swaps operations of two items each. The same items may be swapped multiple times, at least two groups need to be present.")]
+  [StorableClass]
+  public sealed class SwapItemManipulator : LinearLinkageManipulator {
+
+    public IValueLookupParameter<IntValue> NParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["N"]; }
+    }
+
+    [StorableConstructor]
+    private SwapItemManipulator(bool deserializing) : base(deserializing) { }
+    private SwapItemManipulator(SwapItemManipulator original, Cloner cloner) : base(original, cloner) { }
+    public SwapItemManipulator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("N", "The number of swaps to perform.", new IntValue(1)));
+    }
+    public SwapItemManipulator(int n)
+      : this() {
+      NParameter.Value = new IntValue(n);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SwapItemManipulator(this, cloner);
+    }
+
+    public static void Apply(IRandom random, LinearLinkage lle, int n) {
+      var grouping = lle.GetGroups().Select(x => x.ToList()).ToList();
+      if (grouping.Count == 1) return; // nothing can be changed
+
+      var prevGroup = random.Next(grouping.Count);
+      var prevItem = random.Next(grouping[prevGroup].Count);
+      for (var i = 0; i < n; i++) {
+        int nextGroup, nextItem;
+        do {
+          nextGroup = random.Next(grouping.Count);
+          nextItem = random.Next(grouping[nextGroup].Count);
+        } while (nextGroup == prevGroup);
+        var h = grouping[nextGroup][nextItem];
+        grouping[nextGroup][nextItem] = grouping[prevGroup][prevItem];
+        grouping[prevGroup][prevItem] = h;
+        prevGroup = nextGroup;
+        prevItem = nextItem;
+      }
+
+      lle.SetGroups(grouping);
+    }
+
+    protected override void Manipulate(IRandom random, LinearLinkage lle) {
+      var N = NParameter.ActualValue.Value;
+      Apply(random, lle, N);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/ExtractMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/ExtractMove.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/ExtractMove.cs	(revision 14663)
@@ -0,0 +1,60 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public class ExtractMove : Move {
+    public int PreviousItem { get; private set; }
+    public int NextItem { get; private set; }
+
+    private bool IsFirst { get { return PreviousItem == Item; } }
+    private bool IsLast { get { return NextItem == Item; } }
+
+    public ExtractMove(int item, int prev, int next) {
+      Item = item;
+      PreviousItem = prev;
+      NextItem = next;
+    }
+
+    public override void Apply(LinearLinkage lle) {
+      if ((!IsFirst && lle[PreviousItem] != Item)
+        || lle[Item] != NextItem)
+        throw new ArgumentException("Move conditions have changed!");
+      if (!IsFirst) lle[PreviousItem] = IsLast ? PreviousItem : NextItem;
+      lle[Item] = Item;
+    }
+
+    public override void Undo(LinearLinkage lle) {
+      if (!IsFirst && lle[PreviousItem] != (IsLast ? PreviousItem : NextItem)
+        || lle[Item] != Item)
+        throw new ArgumentException("Move conditions have changed, cannot undo move.");
+
+      if (!IsFirst) lle[PreviousItem] = Item;
+      lle[Item] = NextItem;
+    }
+
+    public override void ApplyToLLEb(int[] lleb) {
+      if (!IsLast) lleb[NextItem] = IsFirst ? NextItem : PreviousItem;
+      lleb[Item] = Item;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/MergeMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/MergeMove.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/MergeMove.cs	(revision 14663)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public class MergeMove : Move {
+
+    public int LastItemOfOtherGroup { get; private set; }
+
+    public MergeMove(int item, int lastOfOther) {
+      Item = item;
+      LastItemOfOtherGroup = lastOfOther;
+    }
+
+    public override void Apply(LinearLinkage lle) {
+      if (lle[LastItemOfOtherGroup] != LastItemOfOtherGroup) throw new ArgumentException("Move conditions have changed, group does not terminate at " + LastItemOfOtherGroup);
+      lle[LastItemOfOtherGroup] = Item;
+    }
+
+    public override void Undo(LinearLinkage lle) {
+      if (lle[LastItemOfOtherGroup] != Item) throw new ArgumentException("Move conditions have changed, groups are no longer linked between " + LastItemOfOtherGroup + " and " + Item);
+      lle[LastItemOfOtherGroup] = LastItemOfOtherGroup;
+    }
+
+    public override void ApplyToLLEb(int[] lleb) {
+      lleb[Item] = LastItemOfOtherGroup;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Move.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Move.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Move.cs	(revision 14663)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public abstract class Move {
+    public int Item { get; protected set; }
+
+    public abstract void Apply(LinearLinkage lle);
+    public abstract void Undo(LinearLinkage lle);
+
+    public abstract void ApplyToLLEb(int[] lleb);
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/ShiftMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/ShiftMove.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/ShiftMove.cs	(revision 14663)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public class ShiftMove : Move {
+    public int PreviousItemOfOldGroup { get; private set; }
+    public int PreviousItemOfNewGroup { get; private set; }
+    public int NextItemOfOldGroup { get; private set; }
+    public int NextItemOfNewGroup { get; private set; }
+
+    private bool IsFirst { get { return PreviousItemOfOldGroup == Item; } }
+    private bool IsLast { get { return NextItemOfOldGroup == Item; } }
+    private bool NewGroupClosed { get { return PreviousItemOfNewGroup == NextItemOfNewGroup; } }
+
+    public ShiftMove(int item, int prevOld, int prevNew, int nextOld, int nextNew) {
+      Item = item;
+      PreviousItemOfOldGroup = prevOld;
+      PreviousItemOfNewGroup = prevNew;
+      NextItemOfOldGroup = nextOld;
+      NextItemOfNewGroup = nextNew;
+    }
+
+    public override void Apply(LinearLinkage lle) {
+      if ((!IsFirst && lle[PreviousItemOfOldGroup] != Item)
+        || lle[Item] != NextItemOfOldGroup
+        || lle[PreviousItemOfNewGroup] != NextItemOfNewGroup)
+        throw new ArgumentException("Move conditions have changed!");
+      if (!IsFirst)
+        lle[PreviousItemOfOldGroup] = IsLast ? PreviousItemOfOldGroup : NextItemOfOldGroup;
+      lle[PreviousItemOfNewGroup] = Item;
+      lle[Item] = NewGroupClosed ? Item : NextItemOfNewGroup;
+    }
+
+    public override void Undo(LinearLinkage lle) {
+      if (!IsFirst && lle[PreviousItemOfOldGroup] != (IsLast ? PreviousItemOfOldGroup : NextItemOfOldGroup)
+        || lle[PreviousItemOfNewGroup] != Item
+        || lle[Item] != (NewGroupClosed ? Item : NextItemOfNewGroup))
+        throw new ArgumentException("Move conditions have changed, cannot undo move.");
+
+      if (!IsFirst)
+        lle[PreviousItemOfOldGroup] = Item;
+      lle[PreviousItemOfNewGroup] = NextItemOfNewGroup;
+      lle[Item] = NextItemOfOldGroup;
+    }
+
+    public override void ApplyToLLEb(int[] lleb) {
+      if (!IsLast)
+        lleb[NextItemOfOldGroup] = IsFirst ? NextItemOfOldGroup : PreviousItemOfOldGroup;
+      lleb[Item] = PreviousItemOfNewGroup;
+      if (!NewGroupClosed)
+        lleb[NextItemOfNewGroup] = Item;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/SplitMove.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/SplitMove.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/SplitMove.cs	(revision 14663)
@@ -0,0 +1,51 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public class SplitMove : Move {
+
+    private int nextItem;
+
+    public SplitMove(int item) {
+      Item = item;
+      nextItem = -1;
+    }
+
+    public override void Apply(LinearLinkage lle) {
+      if (lle[Item] == Item) throw new ArgumentException("Move conditions have changed, group is already split at " + Item);
+      nextItem = lle[Item];
+      lle[Item] = Item;
+    }
+
+    public override void Undo(LinearLinkage lle) {
+      if (lle[Item] != Item) throw new ArgumentException("Move conditions have changed, group no longer terminates at " + Item);
+      if (nextItem < 0) throw new InvalidOperationException("Cannot undo move that has not been applied first.");
+      lle[Item] = nextItem;
+    }
+
+    public override void ApplyToLLEb(int[] lleb) {
+      if (nextItem < 0) throw new InvalidOperationException("Cannot undo move that has not been applied first to LLE.");
+      lleb[nextItem] = nextItem;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/StaticAPI/MoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/StaticAPI/MoveGenerator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/StaticAPI/MoveGenerator.cs	(revision 14663)
@@ -0,0 +1,68 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  public static class MoveGenerator {
+    public static IEnumerable<Move> GenerateForItem(int i, List<int> groupItems, LinearLinkage lle, int[] lleb) {
+      var pred = lleb[i];
+      var next = lle[i];
+      var isFirst = pred == i;
+      var isLast = next == i;
+
+      // First: shift i into each previous group
+      foreach (var m in groupItems.Where(x => lle[x] != i)) {
+        yield return new ShiftMove(i, pred, m, next, lle[m]);
+      }
+
+      if (!isLast) {
+        // Second: split group at i
+        yield return new SplitMove(i);
+
+        if (isFirst) {
+          // Third: merge with closed groups
+          foreach (var m in groupItems.Where(x => lle[x] == x)) {
+            yield return new MergeMove(i, m);
+          }
+        } else {
+          // Fourth: extract i into group of its own (exclude first and last, because of SplitMove)
+          yield return new ExtractMove(i, pred, next);
+        }
+      }
+        
+
+    }
+
+    public static IEnumerable<Move> Generate(LinearLinkage lle) {
+      var groupItems = new List<int>();
+      var lleb = lle.ToBackLinks();
+      for (var i = 0; i < lle.Length; i++) {
+        foreach (var move in GenerateForItem(i, groupItems, lle, lleb))
+          yield return move;
+        if (lleb[i] != i)
+          groupItems.Remove(lleb[i]);
+        groupItems.Add(i);
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/ExhaustiveSwap2MoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/ExhaustiveSwap2MoveGenerator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/ExhaustiveSwap2MoveGenerator.cs	(revision 14663)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("ExhaustiveSwap2MoveGenerator", "Generates all possible swap-2 moves from a given permutation.")]
+  [StorableClass]
+  public class ExhaustiveSwap2MoveGenerator : Swap2MoveGenerator, IExhaustiveMoveGenerator {
+    [StorableConstructor]
+    protected ExhaustiveSwap2MoveGenerator(bool deserializing) : base(deserializing) { }
+    protected ExhaustiveSwap2MoveGenerator(ExhaustiveSwap2MoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public ExhaustiveSwap2MoveGenerator() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExhaustiveSwap2MoveGenerator(this, cloner);
+    }
+
+    public static IEnumerable<Swap2Move> Generate(LinearLinkage lle) {
+      int length = lle.Length;
+      if (length == 1) throw new ArgumentException("ExhaustiveSwap2MoveGenerator: There cannot be an Swap move given only one item.", "lle");
+
+      var groups = lle.GetGroups().ToList();
+      if (groups.Count == 1) throw new InvalidOperationException("ExhaustiveSwap2MoveGenerator: Swap moves cannot be applied when there is only one group.");
+
+      for (int i = 0; i < groups.Count; i++)
+        for (int j = i + 1; j < groups.Count; j++)
+          for (var k = 0; k < groups[i].Count; k++)
+            for (var m = 0; m < groups[j].Count; m++) {
+              yield return new Swap2Move(groups[i][k], groups[j][m]);
+            }
+    }
+
+    protected override Swap2Move[] GenerateMoves(LinearLinkage lle) {
+      return Generate(lle).ToArray();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/StochasticSwap2MultiMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/StochasticSwap2MultiMoveGenerator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/StochasticSwap2MultiMoveGenerator.cs	(revision 14663)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("StochasticSwap2MultiMoveGenerator", "Randomly samples n from all possible swap-2 moves from a given lle grouping.")]
+  [StorableClass]
+  public class StochasticSwap2MultiMoveGenerator : Swap2MoveGenerator, IMultiMoveGenerator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+    public IValueLookupParameter<IntValue> SampleSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
+    }
+
+    public IntValue SampleSize {
+      get { return SampleSizeParameter.Value; }
+      set { SampleSizeParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected StochasticSwap2MultiMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected StochasticSwap2MultiMoveGenerator(StochasticSwap2MultiMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public StochasticSwap2MultiMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticSwap2MultiMoveGenerator(this, cloner);
+    }
+
+    public static Swap2Move[] Apply(LinearLinkage lle, IRandom random, int sampleSize) {
+      int length = lle.Length;
+      Swap2Move[] moves = new Swap2Move[sampleSize];
+      for (int i = 0; i < sampleSize; i++) {
+        moves[i] = StochasticSwap2SingleMoveGenerator.Apply(lle, random);
+      }
+      return moves;
+    }
+
+    protected override Swap2Move[] GenerateMoves(LinearLinkage lle) {
+      IRandom random = RandomParameter.ActualValue;
+      return Apply(lle, random, SampleSizeParameter.ActualValue.Value);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/StochasticSwap2SingleMoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/StochasticSwap2SingleMoveGenerator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/StochasticSwap2SingleMoveGenerator.cs	(revision 14663)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("StochasticSwap2SingleMoveGenerator", "Randomly samples a single from all possible swap-2 moves from a given grouping.")]
+  [StorableClass]
+  public class StochasticSwap2SingleMoveGenerator : Swap2MoveGenerator, IStochasticOperator, ISingleMoveGenerator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    [StorableConstructor]
+    protected StochasticSwap2SingleMoveGenerator(bool deserializing) : base(deserializing) { }
+    protected StochasticSwap2SingleMoveGenerator(StochasticSwap2SingleMoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public StochasticSwap2SingleMoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StochasticSwap2SingleMoveGenerator(this, cloner);
+    }
+
+    public static Swap2Move Apply(LinearLinkage lle, IRandom random) {
+      int length = lle.Length;
+      if (length < 2) throw new ArgumentException("StochasticSwap2SingleMoveGenerator: There cannot be a swap-2 move given only one item.", "lle");
+
+      var groups = lle.GetGroups().ToList();
+      if (groups.Count == 1) throw new InvalidOperationException("StochasticSwap2SingleMoveGenerator: Swap moves cannot be applied when there is only one group.");
+
+      int index1 = random.Next(groups.Count), index2 = 0;
+      do {
+        index2 = random.Next(length);
+      } while (index1 == index2);
+
+      var item1 = random.Next(groups[index1].Count);
+      var item2 = random.Next(groups[index2].Count);
+
+      return new Swap2Move(groups[index1][item1], groups[index2][item2]);
+    }
+
+    protected override Swap2Move[] GenerateMoves(LinearLinkage lle) {
+      IRandom random = RandomParameter.ActualValue;
+      return new[] { Apply(lle, random) };
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2Move.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2Move.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2Move.cs	(revision 14663)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Swap2Move", "Item that describes a swap-2 move.")]
+  [StorableClass]
+  public class Swap2Move : Item {
+    [Storable]
+    public int Item1 { get; protected set; }
+    [Storable]
+    public int Item2 { get; protected set; }
+    [Storable]
+    public LinearLinkage LLE { get; protected set; }
+
+    [StorableConstructor]
+    protected Swap2Move(bool deserializing) : base(deserializing) { }
+    protected Swap2Move(Swap2Move original, Cloner cloner) : base(original, cloner) { }
+    public Swap2Move() : this(-1, -1, null) { }
+    public Swap2Move(int item1, int item2) : this(item1, item2, null) { }
+    public Swap2Move(int item1, int item2, LinearLinkage lle)
+      : base() {
+      Item1 = item1;
+      Item2 = item2;
+      LLE = lle;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2Move(this, cloner);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2MoveGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2MoveGenerator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2MoveGenerator.cs	(revision 14663)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Swap2MoveGenerator", "Base class for all swap-2 move generators.")]
+  [StorableClass]
+  public abstract class Swap2MoveGenerator : SingleSuccessorOperator, ILinearLinkageSwap2MoveOperator, IMoveGenerator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<LinearLinkage> LLEParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["LLE"]; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (LookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveGenerator(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveGenerator(Swap2MoveGenerator original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveGenerator()
+      : base() {
+      Parameters.Add(new LookupParameter<LinearLinkage>("LLE", "The LLE solution for which moves should be generated."));
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The moves that should be generated in subscopes."));
+    }
+
+    public override IOperation Apply() {
+      var lle = LLEParameter.ActualValue;
+      var moves = GenerateMoves(lle);
+      var moveScopes = new Scope[moves.Length];
+      for (var i = 0; i < moveScopes.Length; i++) {
+        moveScopes[i] = new Scope(i.ToString());
+        moveScopes[i].Variables.Add(new Variable(Swap2MoveParameter.ActualName, moves[i]));
+      }
+      ExecutionContext.Scope.SubScopes.AddRange(moveScopes);
+      return base.Apply();
+    }
+
+    protected abstract Swap2Move[] GenerateMoves(LinearLinkage lle);
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2MoveMaker.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2MoveMaker.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Moves/Swap/Swap2MoveMaker.cs	(revision 14663)
@@ -0,0 +1,106 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Swap2MoveMaker", "Peforms a swap-2 move on a given grouping and updates the quality.")]
+  [StorableClass]
+  public class Swap2MoveMaker : SingleSuccessorOperator, ILinearLinkageSwap2MoveOperator, IMoveMaker, ISingleObjectiveOperator {
+    public override bool CanChangeName {
+      get { return false; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<DoubleValue> MoveQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
+    }
+    public ILookupParameter<Swap2Move> Swap2MoveParameter {
+      get { return (ILookupParameter<Swap2Move>)Parameters["Swap2Move"]; }
+    }
+    public ILookupParameter<LinearLinkage> LLEParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["LLE"]; }
+    }
+
+    [StorableConstructor]
+    protected Swap2MoveMaker(bool deserializing) : base(deserializing) { }
+    protected Swap2MoveMaker(Swap2MoveMaker original, Cloner cloner) : base(original, cloner) { }
+    public Swap2MoveMaker()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the solution."));
+      Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The move to apply."));
+      Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The relative quality of the move."));
+      Parameters.Add(new LookupParameter<LinearLinkage>("LLE", "The linear linkage encoded solution to which the move should be applied."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Swap2MoveMaker(this, cloner);
+    }
+
+    public static void Apply(LinearLinkage lle, Swap2Move move) {
+      var groups = lle.GetGroups().ToList();
+      int g1 = -1, g2 = -1, g1Idx = -1, g2Idx = -1;
+      for (var i = 0; i < groups.Count; i++) {
+        if (g1 < 0) {
+          g1Idx = groups[i].IndexOf(move.Item1);
+          if (g1Idx >= 0) {
+            g1 = i;
+            continue;
+          }
+        }
+        if (g2 < 0) {
+          g2Idx = groups[i].IndexOf(move.Item2);
+          if (g2Idx >= 0) g2 = i;
+        }
+      }
+
+      // can happen if (for some reason) the items belong to the same group
+      if (g1 < 0 || g2 < 0) throw new InvalidOperationException("Swap2MoveMaker: Cannot apply swap move, items are not found in different groups.");
+
+      var h = groups[g1][g1Idx];
+      groups[g1][g1Idx] = groups[g2][g2Idx];
+      groups[g2][g2Idx] = h;
+      lle.SetGroups(groups);
+    }
+
+    public override IOperation Apply() {
+      var move = Swap2MoveParameter.ActualValue;
+      var lle = LLEParameter.ActualValue;
+      var moveQuality = MoveQualityParameter.ActualValue;
+      var quality = QualityParameter.ActualValue;
+
+      Apply(lle, move);
+
+      quality.Value = moveQuality.Value;
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Plugin.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Plugin.cs.frame	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Plugin.cs.frame	(revision 14663)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Plugin("HeuristicLab.Encodings.LinearLinkageEncoding", "Provides data structures and operators for the linear linkage encoding (LLE).", "3.4.14.$WCREV$")]
+  [PluginFile("HeuristicLab.Encodings.LinearLinkageEncoding-3.4.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  public class HeuristicLabEncodingsLinearLinkageEncodingPlugin : PluginBase { }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Properties/AssemblyInfo.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Properties/AssemblyInfo.cs.frame	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/Properties/AssemblyInfo.cs.frame	(revision 14663)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Encodings.LinearLinkage")]
+[assembly: AssemblyDescription("Linear linkage encoding (LLE) for HeuristicLab")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2016 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1fb5c9e2-42ac-441a-ae79-bfdf261a7262")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.4.0.0")]
+[assembly: AssemblyFileVersion("3.4.14.$WCREV$")]
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/ShakingOperators/LLEShakingOperator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/ShakingOperators/LLEShakingOperator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/ShakingOperators/LLEShakingOperator.cs	(revision 14663)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("LLE Shaking Operator", "A shaking operator for VNS which uses LLE manipulators to perform the shaking.")]
+  [StorableClass]
+  public class LLEShakingOperator : ShakingOperator<ILinearLinkageManipulator>, IStochasticOperator, ILinearLinkageShakingOperator {
+
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public ILookupParameter<LinearLinkage> LLEParameter {
+      get { return (ILookupParameter<LinearLinkage>)Parameters["LLE"]; }
+    }
+
+    public ICheckedItemList<ILinearLinkageManipulator> Shakers {
+      get { return Operators; }
+    }
+
+    [StorableConstructor]
+    protected LLEShakingOperator(bool deserializing) : base(deserializing) { }
+    protected LLEShakingOperator(LLEShakingOperator original, Cloner cloner) : base(original, cloner) { }
+    public LLEShakingOperator()
+      : base() {
+      Parameters.Add(new LookupParameter<LinearLinkage>("LLE", "The encoding to shake."));
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that will be used for stochastic shaking operators."));
+      for (var i = 1; i < 4; i++) {
+        Operators.Add(new MoveItemManipulator(i * 2));
+        Operators.Add(new SwapItemManipulator(i * 2));
+        Operators.Add(new SplitGroupManipulator(i * 2));
+        Operators.Add(new MergeGroupManipulator(i * 2));
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LLEShakingOperator(this, cloner);
+    }
+
+    #region Wiring of some parameters
+    protected override void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<ILinearLinkageManipulator>> e) {
+      base.Operators_ItemsAdded(sender, e);
+      ParameterizeOperators(e.Items);
+    }
+
+    protected override void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<ILinearLinkageManipulator>> e) {
+      base.Operators_ItemsReplaced(sender, e);
+      ParameterizeOperators(e.Items);
+    }
+
+    private void ParameterizeOperators(IEnumerable<IndexedItem<ILinearLinkageManipulator>> items) {
+      if (!items.Any()) return;
+      foreach (var op in items.Select(x => x.Value).OfType<IStochasticOperator>())
+        op.RandomParameter.ActualName = RandomParameter.Name;
+      foreach (var op in items.Select(x => x.Value))
+        op.LLEParameter.ActualName = LLEParameter.Name;
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/SimilarityCalculators/HammingSimilarityCalculator.cs
===================================================================
--- trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/SimilarityCalculators/HammingSimilarityCalculator.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Encodings.LinearLinkageEncoding/3.4/SimilarityCalculators/HammingSimilarityCalculator.cs	(revision 14663)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding {
+  [Item("Hamming Similarity Calculator for LinearLinkage", "Calculates the hamming similarity for two linear linkage encoded solutions.")]
+  [StorableClass]
+  public sealed class HammingSimilarityCalculator : SingleObjectiveSolutionSimilarityCalculator {
+
+    protected override bool IsCommutative {
+      get { return true; }
+    }
+
+    [StorableConstructor]
+    private HammingSimilarityCalculator(bool deserializing) : base(deserializing) { }
+    private HammingSimilarityCalculator(HammingSimilarityCalculator original, Cloner cloner) : base(original, cloner) { }
+    public HammingSimilarityCalculator() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HammingSimilarityCalculator(this, cloner);
+    }
+
+    public static double CalculateSimilarity(LinearLinkage left, LinearLinkage right) {
+      if (left.Length != right.Length) throw new ArgumentException("Comparing encodings of unequal length");
+      var similarity = 0;
+      for (var i = 0; i < left.Length; i++) {
+        if (left[i] == right[i]) similarity++;
+      }
+      return similarity / (double)left.Length;
+    }
+
+    public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) {
+      var left = leftSolution.Variables[SolutionVariableName].Value as LinearLinkage;
+      var right = rightSolution.Variables[SolutionVariableName].Value as LinearLinkage;
+
+      return CalculateSimilarity(left, right);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.Programmable/3.3/HeuristicLab.Problems.Programmable-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.Programmable/3.3/HeuristicLab.Problems.Programmable-3.3.csproj	(revision 14662)
+++ trunk/sources/HeuristicLab.Problems.Programmable/3.3/HeuristicLab.Problems.Programmable-3.3.csproj	(revision 14663)
@@ -149,5 +149,5 @@
       <Name>HeuristicLab.Encodings.IntegerVectorEncoding-3.3</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Encodings.LinearLinkageEncoding\3.3\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj">
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.LinearLinkageEncoding\3.4\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj">
       <Project>{be698769-975a-429e-828c-72bb2b6182c8}</Project>
       <Name>HeuristicLab.Encodings.LinearLinkageEncoding-3.4</Name>
Index: trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/Auxiliary.cs
===================================================================
--- trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/Auxiliary.cs	(revision 14662)
+++ trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/Auxiliary.cs	(revision 14663)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
Index: trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/ConversionsTest.cs
===================================================================
--- trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/ConversionsTest.cs	(revision 14662)
+++ trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/ConversionsTest.cs	(revision 14663)
@@ -1,3 +1,26 @@
-﻿using System;
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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.Linq;
+using HeuristicLab.Random;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
@@ -95,4 +118,22 @@
       }
     }
+
+    [TestMethod]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void ConvertFromLLEtoLLEe() {
+      var random = new MersenneTwister(42);
+      var lle = MaxGroupsLinearLinkageCreator.Apply(random, 32, 8);
+      Assert.IsTrue(lle.SequenceEqual(LinearLinkage.FromEndLinks(lle.ToEndLinks())));
+    }
+
+    [TestMethod]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void ConvertFromLLEtoLLEb() {
+      var random = new MersenneTwister(42);
+      var lle = MaxGroupsLinearLinkageCreator.Apply(random, 32, 8);
+      Assert.IsTrue(lle.SequenceEqual(LinearLinkage.FromBackLinks(lle.ToBackLinks())));
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/GroupCrossoverTest.cs
===================================================================
--- trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/GroupCrossoverTest.cs	(revision 14662)
+++ trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/GroupCrossoverTest.cs	(revision 14663)
@@ -1,3 +1,23 @@
-﻿using System;
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HeuristicLab.Random;
 using HeuristicLab.Tests;
Index: trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/MoveTests.cs
===================================================================
--- trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/MoveTests.cs	(revision 14663)
+++ trunk/sources/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/MoveTests.cs	(revision 14663)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 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 HeuristicLab.Random;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding.Tests {
+  [TestClass]
+  public class LinearLinkageMoveTests {
+    [TestMethod]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void TestLinearLinkageMoveApplyUndo() {
+      var random = new MersenneTwister(42);
+      for (var p = 0; p < 7; p++) {
+        var lle = ExactGroupsLinearLinkageCreator.Apply(random, 64, (int)Math.Pow(2, p));
+        var before = (LinearLinkage)lle.Clone();
+        var beforeb = before.ToBackLinks();
+        var moves = 0;
+        foreach (var move in MoveGenerator.Generate(lle)) {
+          var lleb = lle.ToBackLinks();
+          move.Apply(lle);
+          move.ApplyToLLEb(lleb);
+          Assert.IsFalse(before.SequenceEqual(lle));
+          Assert.IsFalse(lleb.SequenceEqual(beforeb));
+          Assert.IsTrue(lleb.SequenceEqual(lle.ToBackLinks()));
+          Assert.IsTrue(lle.SequenceEqual(LinearLinkage.FromBackLinks(lleb)));
+          move.Undo(lle);
+          Assert.IsTrue(before.SequenceEqual(lle));
+          moves++;
+        }
+        Assert.IsTrue(moves > 0);
+      }
+    }
+
+    [TestMethod]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void TestLinearLinkageMoveApply() {
+      var random = new MersenneTwister(42);
+      for (var p = 0; p < 7; p++) {
+        var lle = ExactGroupsLinearLinkageCreator.Apply(random, 64, (int)Math.Pow(2, p));
+        var lleb = lle.ToBackLinks();
+        var groupItems = new List<int>() { 0 };
+        var moves = 0;
+        for (var i = 1; i < lle.Length; i++) {
+          var move = MoveGenerator.GenerateForItem(i, groupItems, lle, lleb).SampleRandom(random);
+          move.Apply(lle);
+          move.ApplyToLLEb(lleb);
+          Assert.IsTrue(lleb.SequenceEqual(lle.ToBackLinks()));
+          Assert.IsTrue(lle.SequenceEqual(LinearLinkage.FromBackLinks(lleb)));
+
+          if (lleb[i] != i)
+            groupItems.Remove(lleb[i]);
+          groupItems.Add(i);
+
+          moves++;
+        }
+        Assert.IsTrue(moves == lle.Length - 1);
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- trunk/sources/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 14662)
+++ trunk/sources/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 14663)
@@ -512,4 +512,5 @@
     <Compile Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4\ConversionsTest.cs" />
     <Compile Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4\GroupCrossoverTest.cs" />
+    <Compile Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4\MoveTests.cs" />
     <Compile Include="HeuristicLab.Encodings.PermutationEncoding-3.3\Auxiliary.cs" />
     <Compile Include="HeuristicLab.Encodings.PermutationEncoding-3.3\CosaCrossoverTest.cs" />
