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);
+      }
+    }
+  }
+}
