Index: branches/LinearLinkage/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LargestGroupFirstCrossover.cs
===================================================================
--- branches/LinearLinkage/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LargestGroupFirstCrossover.cs	(revision 12285)
+++ 	(revision )
@@ -1,104 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-
-namespace HeuristicLab.Encodings.LinearLinkageEncoding {
-  [Item("Largest Group First Crossover", "")]
-  [StorableClass]
-  public sealed class LargestGroupFirstCrossover : LinearLinkageCrossover {
-
-    [StorableConstructor]
-    private LargestGroupFirstCrossover(bool deserializing) : base(deserializing) { }
-    private LargestGroupFirstCrossover(LargestGroupFirstCrossover original, Cloner cloner) : base(original, cloner) { }
-    public LargestGroupFirstCrossover() { }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new LargestGroupFirstCrossover(this, cloner);
-    }
-
-    public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) {
-      var len = p1.Length;
-      var groups1 = p1.GetGroups().ToList();
-      var groups2 = p2.GetGroups().ToList();
-      var childGroup = new List<HashSet<int>>();
-
-      var total = 0;
-      do {
-        var leastLinks = int.MaxValue;
-        var g1 = -1;
-        var g2 = -1;
-        var comparisons = 0;
-        // find those two groups in both parents that could be merged with least amount of new links
-        // put a bias on bigger groups in parent 1
-        for (var i = 0; i < groups1.Count; i++) {
-          var set1 = new HashSet<int>(groups1[i]);
-          for (var j = 0; j < groups2.Count; j++) {
-            var set2 = new HashSet<int>(groups2[j]);
-            var newLinks = set1.Except(set2).Count() * set2.Except(set1).Count();
-            if (newLinks < leastLinks || newLinks == leastLinks && groups1[i].Count > groups1[g1].Count) {
-              leastLinks = newLinks;
-              g1 = i;
-              g2 = j;
-              comparisons = 1;
-            } else if (newLinks == leastLinks && groups1[i].Count == groups1[g1].Count &&
-                       random.NextDouble() < 1.0 / (++comparisons)) {
-              leastLinks = newLinks;
-              g1 = i;
-              g2 = j;
-            }
-          }
-        }
-        var crossedGroup = new HashSet<int>(groups1[g1].Concat(groups2[g2]));
-        groups1.RemoveAt(g1);
-        groups2.RemoveAt(g2);
-        for (var i = 0; i < groups1.Count; i++) {
-          groups1[i] = groups1[i].Except(crossedGroup).ToList();
-          if (groups1[i].Count != 0) continue;
-          groups1.RemoveAt(i);
-          i--;
-        }
-        for (var i = 0; i < groups2.Count; i++) {
-          groups2[i] = groups2[i].Except(crossedGroup).ToList();
-          if (groups2[i].Count != 0) continue;
-          groups2.RemoveAt(i);
-          i--;
-        }
-        childGroup.Add(crossedGroup);
-        total += crossedGroup.Count;
-      } while (total < len);
-
-      var child = new LinearLinkage(len);
-      child.SetGroups(childGroup);
-      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: branches/LinearLinkage/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/MultiLLECrossover.cs
===================================================================
--- branches/LinearLinkage/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/MultiLLECrossover.cs	(revision 12286)
+++ branches/LinearLinkage/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/MultiLLECrossover.cs	(revision 12286)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.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))) {
+        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();
+    }
+  }
+}
