Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/HeuristicLab.Networks.IntegratedOptimization.LocationRouting-3.3.csproj
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/HeuristicLab.Networks.IntegratedOptimization.LocationRouting-3.3.csproj	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/HeuristicLab.Networks.IntegratedOptimization.LocationRouting-3.3.csproj	(revision 14621)
@@ -180,4 +180,8 @@
     <None Include="Properties\AssemblyInfo.cs.frame" />
     <None Include="Plugin.cs.frame" />
+    <Compile Include="LrpNetwork.cs" />
+    <Compile Include="LrpNetwork2.cs" />
+    <Compile Include="LrpOrchestratorNode.cs" />
+    <Compile Include="LrpOrchestratorNode2.cs" />
     <Compile Include="LrpUtils.cs" />
     <Compile Include="LrpNetwork1.cs" />
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork.cs	(revision 14621)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork.cs	(revision 14621)
@@ -0,0 +1,170 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Core.Networks;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Networks.IntegratedOptimization.LocationRouting {
+  [Item("LrpNetwork", "An abstract base class for LRP optimization networks.")]
+  [StorableClass]
+  public abstract class LrpNetwork : Network {
+    #region
+    protected const string OrchestratorNodeName = "Orchestrator";
+    protected const string MetaSolverNodeName = "MetaSolver";
+    protected const string FlpSolverNodeName = "FlpSolver";
+    protected const string VrpSolverNodeName = "VrpSolver";
+    #endregion
+
+    #region Nodes
+    public LrpOrchestratorNode Orchestrator {
+      get { return (LrpOrchestratorNode)Nodes[OrchestratorNodeName]; }
+      protected set {
+        if (Nodes.ContainsKey(OrchestratorNodeName))
+          throw new InvalidOperationException("Orchestrator already set.");
+        Nodes.Add(value);
+      }
+    }
+
+    public OrchestratedAlgorithmNode MetaSolver {
+      get { return (OrchestratedAlgorithmNode)Nodes[MetaSolverNodeName]; }
+      protected set {
+        if (Nodes.ContainsKey(MetaSolverNodeName))
+          throw new InvalidOperationException("MetaSolver already set.");
+        Nodes.Add(value);
+        RegisterEvents();
+      }
+    }
+
+    public OrchestratedAlgorithmNode FlpSolver {
+      get { return (OrchestratedAlgorithmNode)Nodes[FlpSolverNodeName]; }
+      protected set {
+        if (Nodes.ContainsKey(FlpSolverNodeName))
+          throw new InvalidOperationException("FlpSolver already set.");
+        Nodes.Add(value);
+      }
+    }
+
+    public OrchestratedAlgorithmNode VrpSolver {
+      get { return (OrchestratedAlgorithmNode)Nodes[VrpSolverNodeName]; }
+      protected set {
+        if (Nodes.ContainsKey(VrpSolverNodeName))
+          throw new InvalidOperationException("VrpSolver already set.");
+        Nodes.Add(value);
+      }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected LrpNetwork(bool deserializing) : base(deserializing) { }
+    protected LrpNetwork(LrpNetwork original, Cloner cloner) : base(original, cloner) {
+      RegisterEvents();
+    }
+    protected LrpNetwork() : this("LrpNetwork") { }
+    protected LrpNetwork(string name) : base(name) { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEvents();
+    }
+
+    private void RegisterEvents() {
+      MetaSolver.AlgorithmChanged += MetaSolver_AlgorithmChanged;
+      RegisterAlgorithmEvents();
+    }
+
+    private void MetaSolver_AlgorithmChanged(object sender, EventArgs e) {
+      RegisterAlgorithmEvents();
+    }
+
+    private void RegisterAlgorithmEvents() {
+      var algorithm = MetaSolver.Algorithm;
+      if (algorithm == null) return;
+
+      algorithm.ExecutionStateChanged += (s, e) => OnExecutionStateChanged();
+      algorithm.ExecutionTimeChanged += (s, e) => OnExecutionTimeChanged();
+      algorithm.Prepared += (s, e) => OnPrepared();
+      algorithm.Started += (s, e) => OnStarted();
+      algorithm.Paused += (s, e) => OnPaused();
+      algorithm.Stopped += (s, e) => OnStopped();
+      algorithm.ExceptionOccurred += (s, e) => OnExceptionOccurred(e.Value);
+    }
+
+    #region IOptimizer Members
+    public RunCollection Runs { get { return MetaSolver.Algorithm.Runs; } }
+    public IEnumerable<IOptimizer> NestedOptimizers { get { yield break; } }
+    public ExecutionState ExecutionState { get { return MetaSolver.Algorithm.ExecutionState; } }
+    public TimeSpan ExecutionTime { get { return MetaSolver.Algorithm.ExecutionTime; } }
+
+    public void Prepare() { Prepare(false); }
+    public void Prepare(bool clearRuns) { Orchestrator.Prepare(clearRuns); }
+    public void Start() { Orchestrator.StartAsync(); }
+    public void Pause() { Orchestrator.Pause(); }
+    public void Stop() { Orchestrator.Stop(); }
+
+    public event EventHandler ExecutionStateChanged;
+    private void OnExecutionStateChanged() {
+      var handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ExecutionTimeChanged;
+    private void OnExecutionTimeChanged() {
+      var handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Prepared;
+    private void OnPrepared() {
+      var handler = Prepared;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Started;
+    private void OnStarted() {
+      var handler = Started;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Paused;
+    private void OnPaused() {
+      var handler = Paused;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Stopped;
+    private void OnStopped() {
+      var handler = Stopped;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
+    private void OnExceptionOccurred(Exception exception) {
+      var handler = ExceptionOccurred;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+    #endregion
+  }
+}
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork1.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork1.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork1.cs	(revision 14621)
@@ -21,5 +21,4 @@
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Algorithms.CMAEvolutionStrategy;
@@ -27,5 +26,4 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Core.Networks;
 using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -40,33 +38,15 @@
   [Creatable("Optimization Networks")]
   [StorableClass]
-  public sealed class LrpNetwork1 : Network, IOptimizer {
-    #region Nodes
-    public LrpOrchestratorNode1 Orchestrator {
-      get { return (LrpOrchestratorNode1)Nodes["Orchestrator"]; }
-    }
-
-    public OrchestratedAlgorithmNode MetaSolver {
-      get { return (OrchestratedAlgorithmNode)Nodes["MetaSolver"]; }
-    }
-
-    public OrchestratedAlgorithmNode LrpSolver {
-      get { return (OrchestratedAlgorithmNode)Nodes["LrpSolver"]; }
-    }
-
-    public OrchestratedAlgorithmNode VrpSolver {
-      get { return (OrchestratedAlgorithmNode)Nodes["VrpSolver"]; }
-    }
-    #endregion
-
+  public sealed class LrpNetwork1 : LrpNetwork, IOptimizer {
     [StorableConstructor]
     private LrpNetwork1(bool deserializing) : base(deserializing) { }
-    private LrpNetwork1(LrpNetwork1 original, Cloner cloner) : base(original, cloner) {
-      RegisterEvents();
-    }
-    public LrpNetwork1() : base("LrpNetwork1") {
-      var orchestratorNode = new LrpOrchestratorNode1("Orchestrator");
-      Nodes.Add(orchestratorNode);
+    private LrpNetwork1(LrpNetwork1 original, Cloner cloner) : base(original, cloner) { }
+    public LrpNetwork1() : this("LrpNetwork1") { }
+    public LrpNetwork1(string name) : base(name) {
+      Orchestrator = new LrpOrchestratorNode1(OrchestratorNodeName);
+      MetaSolver = new OrchestratedAlgorithmNode(MetaSolverNodeName);
+      FlpSolver = new OrchestratedAlgorithmNode(FlpSolverNodeName);
+      VrpSolver = new OrchestratedAlgorithmNode(VrpSolverNodeName);
 
-      var metaSolverNode = new OrchestratedAlgorithmNode("MetaSolver");
       var cmaes = new CMAEvolutionStrategy();
       var vp = new VariegationProblem();
@@ -74,17 +54,13 @@
       cmaes.Problem = vp;
       cmaes.MaximumGenerations = 80;
-      metaSolverNode.Algorithm = cmaes;
-      orchestratorNode.MetaSolverOrchestrationPort.ConnectedPort = metaSolverNode.OrchestrationPort;
-      Nodes.Add(metaSolverNode);
+      MetaSolver.Algorithm = cmaes;
+      Orchestrator.MetaSolverOrchestrationPort.ConnectedPort = MetaSolver.OrchestrationPort;
 
-      var flpSolverNode = new OrchestratedAlgorithmNode("FlpSolver");
       var cplexSolver = new FLPCplexSolver();
       cplexSolver.Problem = new FacilityLocationProblem();
       cplexSolver.MaximumRuntimeParameter.Value.Value = TimeSpan.FromSeconds(3.0);
-      flpSolverNode.Algorithm = cplexSolver;
-      orchestratorNode.FlpSolverOrchestrationPort.ConnectedPort = flpSolverNode.OrchestrationPort;
-      Nodes.Add(flpSolverNode);
+      FlpSolver.Algorithm = cplexSolver;
+      Orchestrator.FlpSolverOrchestrationPort.ConnectedPort = FlpSolver.OrchestrationPort;
 
-      var vrpSolverNode = new OrchestratedAlgorithmNode("VrpSolver");
       var ga = new GeneticAlgorithm();
       ga.Problem = new VehicleRoutingProblem();
@@ -97,9 +73,6 @@
       var selector = ga.SelectorParameter.ValidValues.OfType<TournamentSelector>().Single();
       ga.SelectorParameter.Value = selector;
-      vrpSolverNode.Algorithm = ga;
-      orchestratorNode.VrpSolverOrchestrationPort.ConnectedPort = vrpSolverNode.OrchestrationPort;
-      Nodes.Add(vrpSolverNode);
-
-      RegisterEvents();
+      VrpSolver.Algorithm = ga;
+      Orchestrator.VrpSolverOrchestrationPort.ConnectedPort = VrpSolver.OrchestrationPort;
     }
 
@@ -107,94 +80,4 @@
       return new LrpNetwork1(this, cloner);
     }
-
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      RegisterEvents();
-    }
-
-    private void RegisterEvents() {
-      MetaSolver.AlgorithmChanged += MetaSolver_AlgorithmChanged;
-      RegisterAlgorithmEvents();
-    }
-
-    private void RegisterAlgorithmEvents() {
-      var algorithm = MetaSolver.Algorithm;
-      if (algorithm == null) return;
-
-      algorithm.ExecutionStateChanged += OnExecutionStateChanged;
-      algorithm.ExecutionTimeChanged += OnExecutionTimeChanged;
-      algorithm.Prepared += OnPrepared;
-      algorithm.Started += OnStarted;
-      algorithm.Paused += OnPaused;
-      algorithm.Stopped += OnStopped;
-      algorithm.ExceptionOccurred += OnExceptionOccurred;
-    }
-
-    private void MetaSolver_AlgorithmChanged(object sender, EventArgs e) {
-      RegisterAlgorithmEvents();
-    }
-
-    #region IOptimizer Members
-    public RunCollection Runs { get { return MetaSolver.Algorithm.Runs; } }
-    public IEnumerable<IOptimizer> NestedOptimizers { get { yield break; } }
-    public ExecutionState ExecutionState { get { return MetaSolver.Algorithm.ExecutionState; } }
-    public TimeSpan ExecutionTime { get { return MetaSolver.Algorithm.ExecutionTime; } }
-
-    public void Prepare() { Prepare(false); }
-    public void Prepare(bool clearRuns) { Orchestrator.Prepare(clearRuns); }
-    public void Start() { Orchestrator.StartAsync(); }
-    public void Pause() { Orchestrator.Pause(); }
-    public void Stop() { Orchestrator.Stop(); }
-    #endregion
-
-    private void OnExecutionStateChanged(object sender, EventArgs e) { OnExecutionStateChanged(); }
-    private void OnExecutionTimeChanged(object sender, EventArgs e) { OnExecutionTimeChanged(); }
-    private void OnPrepared(object sender, EventArgs e) { OnPrepared(); }
-    private void OnStarted(object sender, EventArgs e) { OnStarted(); }
-    private void OnPaused(object sender, EventArgs e) { OnPaused(); }
-    private void OnStopped(object sender, EventArgs e) { OnStopped(); }
-    private void OnExceptionOccurred(object sender, EventArgs<Exception> e) { OnExceptionOccurred(e.Value); }
-
-    public event EventHandler ExecutionStateChanged;
-    private void OnExecutionStateChanged() {
-      var handler = ExecutionStateChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ExecutionTimeChanged;
-    private void OnExecutionTimeChanged() {
-      var handler = ExecutionTimeChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler Prepared;
-    private void OnPrepared() {
-      var handler = Prepared;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler Started;
-    private void OnStarted() {
-      var handler = Started;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler Paused;
-    private void OnPaused() {
-      var handler = Paused;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler Stopped;
-    private void OnStopped() {
-      var handler = Stopped;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
-    private void OnExceptionOccurred(Exception exception) {
-      var handler = ExceptionOccurred;
-      if (handler != null) handler(this, new EventArgs<Exception>(exception));
-    }
   }
 }
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork2.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork2.cs	(revision 14621)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpNetwork2.cs	(revision 14621)
@@ -0,0 +1,83 @@
+﻿#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.Algorithms.CMAEvolutionStrategy;
+using HeuristicLab.Algorithms.GeneticAlgorithm;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.FacilityLocation;
+using HeuristicLab.Problems.FacilityLocation.CplexSolver;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Selection;
+
+namespace HeuristicLab.Networks.IntegratedOptimization.LocationRouting {
+  [Item("LrpNetwork2", "Version 2 of a TTP optimization network.")]
+  [Creatable("Optimization Networks")]
+  [StorableClass]
+  public sealed class LrpNetwork2 : LrpNetwork, IOptimizer {
+    [StorableConstructor]
+    private LrpNetwork2(bool deserializing) : base(deserializing) { }
+    private LrpNetwork2(LrpNetwork2 original, Cloner cloner) : base(original, cloner) { }
+    public LrpNetwork2() : this("LrpNetwork2") { }
+    public LrpNetwork2(string name) : base(name) {
+      Orchestrator = new LrpOrchestratorNode2(OrchestratorNodeName);
+      MetaSolver = new OrchestratedAlgorithmNode(MetaSolverNodeName);
+      FlpSolver = new OrchestratedAlgorithmNode(FlpSolverNodeName);
+      VrpSolver = new OrchestratedAlgorithmNode(VrpSolverNodeName);
+
+      var cmaes = new CMAEvolutionStrategy();
+      var vp = new VariegationProblem();
+      vp.SetMaximization(false);
+      cmaes.Problem = vp;
+      cmaes.MaximumGenerations = 80;
+      MetaSolver.Algorithm = cmaes;
+      Orchestrator.MetaSolverOrchestrationPort.ConnectedPort = MetaSolver.OrchestrationPort;
+
+      var cplexSolver = new FLPCplexSolver();
+      cplexSolver.Problem = new FacilityLocationProblem();
+      cplexSolver.MaximumRuntimeParameter.Value.Value = TimeSpan.FromSeconds(3.0);
+      FlpSolver.Algorithm = cplexSolver;
+      Orchestrator.FlpSolverOrchestrationPort.ConnectedPort = FlpSolver.OrchestrationPort;
+
+      var ga = new GeneticAlgorithm();
+      ga.Problem = new VehicleRoutingProblem();
+      ga.PopulationSize.Value = 100;
+      var crossover = ga.CrossoverParameter.ValidValues.OfType<MultiVRPSolutionCrossover>().Single(x => x.Name == "MultiVRPSolutionCrossover");
+      ga.CrossoverParameter.Value = crossover;
+      ga.MaximumGenerations.Value = 100;
+      var mutator = ga.MutatorParameter.ValidValues.OfType<MultiVRPSolutionManipulator>().Single(x => x.Name == "MultiVRPSolutionManipulator");
+      ga.MutatorParameter.Value = mutator;
+      var selector = ga.SelectorParameter.ValidValues.OfType<TournamentSelector>().Single();
+      ga.SelectorParameter.Value = selector;
+      VrpSolver.Algorithm = ga;
+      Orchestrator.VrpSolverOrchestrationPort.ConnectedPort = VrpSolver.OrchestrationPort;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LrpNetwork2(this, cloner);
+    }
+  }
+}
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode.cs	(revision 14621)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode.cs	(revision 14621)
@@ -0,0 +1,332 @@
+﻿#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 System.Text.RegularExpressions;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Core.Networks;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.FacilityLocation;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.Encodings.General;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Networks.IntegratedOptimization.LocationRouting {
+  [Item("LrpOrchestratorNode", "An abstract base class for orchestrators used in LRP optimization networks.")]
+  [StorableClass]
+  public abstract class LrpOrchestratorNode : OrchestratorNode {
+    #region Constants
+    protected const string InstanceParameterName = "Instance";
+    protected const string FlpParameterName = "FLP";
+    protected const string VrpParameterName = "VRP";
+    protected const string MetaSolverName = "MetaSolver";
+    protected const string FlpSolverName = "FlpSolver";
+    protected const string VrpSolverName = "VrpSolver";
+    #endregion
+
+    protected CancellationTokenSource cts;
+    protected ResultCollection flpResults, vrpResults;
+
+    [Storable]
+    protected int nrOfDepots, nrOfCustomers;
+    [Storable]
+    protected double[,] depotCoordinates = new double[0, 0], customerCoordinates = new double[0, 0];
+    [Storable]
+    protected LrpUtils.DistanceType distanceType;
+    [Storable]
+    protected double[] depotCapacities = new double[0], customerDemands = new double[0], depotCosts = new double[0];
+    [Storable]
+    protected double vehicleCapacity, vehicleCost;
+
+    #region Parameters
+    public IFixedValueParameter<TextFileValue> InstanceParameter {
+      get { return (IFixedValueParameter<TextFileValue>)Parameters[InstanceParameterName]; }
+    }
+
+    public IValueParameter<FacilityLocationProblem> FlpParameter {
+      get { return (IValueParameter<FacilityLocationProblem>)Parameters[FlpParameterName]; }
+    }
+
+    public IValueParameter<VehicleRoutingProblem> VrpParameter {
+      get { return (IValueParameter<VehicleRoutingProblem>)Parameters[VrpParameterName]; }
+    }
+    #endregion
+
+    #region Ports
+    public IMessagePort MetaSolverOrchestrationPort {
+      get { return (IMessagePort)Ports[MetaSolverName + OrchestrationPortNameSuffix]; }
+      protected set {
+        string portName = MetaSolverName + OrchestrationPortNameSuffix;
+        if (Ports.ContainsKey(portName))
+          throw new InvalidOperationException(portName + " already set.");
+        Ports.Add(value);
+        value.ConnectedPortChanged += MetaSolverOrchestrationPort_ConnectedPortChanged;
+      }
+    }
+
+    public IMessagePort MetaSolverEvaluationPort {
+      get { return (IMessagePort)Ports[MetaSolverName + EvaluationPortNameSuffix]; }
+      protected set {
+        string portName = MetaSolverName + EvaluationPortNameSuffix;
+        if (Ports.ContainsKey(portName))
+          throw new InvalidOperationException(portName + " already set.");
+        Ports.Add(value);
+      }
+    }
+
+    public IMessagePort FlpSolverOrchestrationPort {
+      get { return (IMessagePort)Ports[FlpSolverName + OrchestrationPortNameSuffix]; }
+      protected set {
+        string portName = FlpSolverName + OrchestrationPortNameSuffix;
+        if (Ports.ContainsKey(portName))
+          throw new InvalidOperationException(portName + " already set.");
+        Ports.Add(value);
+        value.ConnectedPortChanged += FlpSolverOrchestrationPort_ConnectedPortChanged;
+      }
+    }
+
+    public IMessagePort FlpSolverEvaluationPort {
+      get { return (IMessagePort)Ports[FlpSolverName + EvaluationPortNameSuffix]; }
+      protected set {
+        string portName = FlpSolverName + EvaluationPortNameSuffix;
+        if (Ports.ContainsKey(portName))
+          throw new InvalidOperationException(portName + " already set.");
+        Ports.Add(value);
+      }
+    }
+
+    public IMessagePort VrpSolverOrchestrationPort {
+      get { return (IMessagePort)Ports[VrpSolverName + OrchestrationPortNameSuffix]; }
+      protected set {
+        string portName = VrpSolverName + OrchestrationPortNameSuffix;
+        if (Ports.ContainsKey(portName))
+          throw new InvalidOperationException(portName + " already set.");
+        Ports.Add(value);
+        value.ConnectedPortChanged += VrpSolverOrchestrationPort_ConnectedPortChanged;
+      }
+    }
+
+    public IMessagePort VrpSolverEvaluationPort {
+      get { return (IMessagePort)Ports[VrpSolverName + EvaluationPortNameSuffix]; }
+      protected set {
+        string portName = VrpSolverName + EvaluationPortNameSuffix;
+        if (Ports.ContainsKey(portName))
+          throw new InvalidOperationException(portName + " already set.");
+        Ports.Add(value);
+      }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected LrpOrchestratorNode(bool deserializing) : base(deserializing) { }
+    protected LrpOrchestratorNode(LrpOrchestratorNode original, Cloner cloner) : base(original, cloner) {
+      nrOfDepots = original.nrOfDepots;
+      nrOfCustomers = original.nrOfCustomers;
+      depotCoordinates = (double[,])original.depotCoordinates.Clone();
+      customerCoordinates = (double[,])original.customerCoordinates.Clone();
+      distanceType = original.distanceType;
+      depotCapacities = (double[])original.depotCapacities.Clone();
+      customerDemands = (double[])original.customerDemands.Clone();
+      depotCosts = (double[])original.depotCosts.Clone();
+      vehicleCapacity = original.vehicleCapacity;
+      vehicleCost = original.vehicleCost;
+
+      RegisterEvents();
+    }
+    protected LrpOrchestratorNode() : this("LrpOrchestratorNode") { }
+    protected LrpOrchestratorNode(string name) : base(name) {
+      Parameters.Add(new FixedValueParameter<TextFileValue>(InstanceParameterName));
+      Parameters.Add(new ValueParameter<FacilityLocationProblem>(FlpParameterName, new FacilityLocationProblem()));
+      Parameters.Add(new ValueParameter<VehicleRoutingProblem>(VrpParameterName, new VehicleRoutingProblem() { ProblemInstance = new CVRPProblemInstance() }));
+
+      InstanceParameter.Value.ToStringChanged += InstanceParameter_Value_ToStringChanged;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEvents();
+    }
+
+    private void RegisterEvents() {
+      InstanceParameter.Value.ToStringChanged += InstanceParameter_Value_ToStringChanged;
+      MetaSolverOrchestrationPort.ConnectedPortChanged += MetaSolverOrchestrationPort_ConnectedPortChanged;
+      FlpSolverOrchestrationPort.ConnectedPortChanged += FlpSolverOrchestrationPort_ConnectedPortChanged;
+      VrpSolverOrchestrationPort.ConnectedPortChanged += VrpSolverOrchestrationPort_ConnectedPortChanged;
+    }
+
+    private void InstanceParameter_Value_ToStringChanged(object sender, EventArgs e) {
+      string filePath = InstanceParameter.Value.Value;
+      LrpUtils.Import(filePath, out nrOfDepots, out nrOfCustomers,
+                                out depotCoordinates, out customerCoordinates,
+                                out distanceType,
+                                out depotCapacities, out customerDemands, out depotCosts,
+                                out vehicleCapacity, out vehicleCost);
+
+      var flp = FlpParameter.Value;
+      flp.CustomerDemandsParameter.Value = new DoubleArray(customerDemands);
+      flp.DeliveryCostsParameter.Value = new DoubleMatrix(LrpUtils.GetFlpDeliveryCosts(depotCoordinates, customerCoordinates, distanceType));
+      flp.DepotCapacitiesParameter.Value = new DoubleArray(depotCapacities);
+      flp.Encoding.Length = nrOfCustomers;
+      flp.OpeningCostsParameter.Value = new DoubleArray(depotCosts);
+
+      var vrpInstance = (CVRPProblemInstance)VrpParameter.Value.ProblemInstance;
+      vrpInstance.Capacity.Value = vehicleCapacity;
+      vrpInstance.FleetUsageFactor.Value = vehicleCost;
+      vrpInstance.OverloadPenalty.Value = vehicleCost * 1000.0;
+
+      var crossover = VrpParameter.Value.OperatorsParameter.Value.OfType<MultiVRPSolutionCrossover>().Single(x => x.Name == "MultiVRPSolutionCrossover");
+      foreach (var c in crossover.Operators)
+        crossover.Operators.SetItemCheckedState(c, c.Name.StartsWith("Potvin"));
+      var mutator = VrpParameter.Value.OperatorsParameter.Value.OfType<MultiVRPSolutionManipulator>().Single(x => x.Name == "MultiVRPSolutionManipulator");
+      foreach (var m in mutator.Operators)
+        mutator.Operators.SetItemCheckedState(m, Regex.IsMatch(m.Name, @"Potvin(One|Two).*"));
+
+      Prepare();
+    }
+
+    protected virtual void MetaSolverOrchestrationPort_ConnectedPortChanged(object sender, EventArgs e) {
+      if (MetaSolverOrchestrationPort.ConnectedPort == null) return;
+
+      var node = MetaSolverOrchestrationPort.ConnectedPort.Parent as OrchestratedAlgorithmNode;
+      if (node == null) return;
+
+      var hook = new HookOperator { Name = "Meta Eval Hook" };
+      hook.Parameters.Add(new LookupParameter<RealVector>("RealVector") { Hidden = true });
+      hook.Parameters.Add(new LookupParameter<DoubleValue>("Quality") { Hidden = true });
+      node.EvalHook = hook;
+
+      node.OrchestrationPort.CloneParametersFromPort(MetaSolverOrchestrationPort);
+      node.EvaluationPort.CloneParametersFromPort(MetaSolverEvaluationPort);
+      node.EvaluationPort.ConnectedPort = MetaSolverEvaluationPort;
+    }
+
+    protected virtual void FlpSolverOrchestrationPort_ConnectedPortChanged(object sender, EventArgs e) {
+      if (FlpSolverOrchestrationPort.ConnectedPort == null) return;
+
+      var node = FlpSolverOrchestrationPort.ConnectedPort.Parent as OrchestratedAlgorithmNode;
+      if (node == null) return;
+
+      node.OrchestrationPort.CloneParametersFromPort(FlpSolverOrchestrationPort);
+    }
+
+    protected virtual void VrpSolverOrchestrationPort_ConnectedPortChanged(object sender, EventArgs e) {
+      if (VrpSolverOrchestrationPort.ConnectedPort == null) return;
+
+      var node = VrpSolverOrchestrationPort.ConnectedPort.Parent as OrchestratedAlgorithmNode;
+      if (node == null) return;
+
+      node.OrchestrationPort.CloneParametersFromPort(VrpSolverOrchestrationPort);
+    }
+
+    public override void Prepare(bool clearRuns = false) {
+      Results.Clear();
+    }
+
+    public override void Start() {
+      cts = new CancellationTokenSource();
+
+      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
+      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Start);
+      MetaSolverOrchestrationPort.SendMessage(metaMsg);
+    }
+
+    public override void Pause() {
+      cts.Cancel();
+
+      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
+      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Pause);
+      MetaSolverOrchestrationPort.SendMessage(metaMsg);
+
+      var flpMsg = FlpSolverOrchestrationPort.PrepareMessage();
+      flpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
+      FlpSolverOrchestrationPort.SendMessage(flpMsg);
+
+      var vrpMsg = VrpSolverOrchestrationPort.PrepareMessage();
+      vrpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
+      VrpSolverOrchestrationPort.SendMessage(vrpMsg);
+    }
+
+    public override void Stop() {
+      cts.Cancel();
+
+      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
+      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
+      MetaSolverOrchestrationPort.SendMessage(metaMsg);
+
+      var flpMsg = FlpSolverOrchestrationPort.PrepareMessage();
+      flpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
+      FlpSolverOrchestrationPort.SendMessage(flpMsg);
+
+      var vrpMsg = VrpSolverOrchestrationPort.PrepareMessage();
+      vrpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
+      VrpSolverOrchestrationPort.SendMessage(vrpMsg);
+    }
+
+    protected override void ProcessMessage(IMessage message, IMessagePort port, CancellationToken token) {
+      var messageActions = new Dictionary<IMessagePort, Action<IMessage>>();
+      messageActions.Add(MetaSolverOrchestrationPort, MetaSolverOrchestrationPortMessage);
+      messageActions.Add(MetaSolverEvaluationPort, MetaSolverEvaluationPortMessage);
+      messageActions.Add(FlpSolverOrchestrationPort, FlpSolverOrchestrationPortMessage);
+      messageActions.Add(VrpSolverOrchestrationPort, VrpSolverOrchestrationPortMessage);
+
+      messageActions[port](message);
+
+      base.ProcessMessage(message, port, token);
+    }
+
+    #region MetaSolver Message Handling
+    protected virtual void MetaSolverOrchestrationPortMessage(IMessage message) { }
+
+    protected virtual void MetaSolverEvaluationPortMessage(IMessage message) { }
+    #endregion
+
+    #region FlpSolver Message Handling
+    protected virtual void FlpSolverOrchestrationPortMessage(IMessage message) {
+      var results = (ResultCollection)message["Results"];
+      if (results.ContainsKey("Best Solution")) {
+        flpResults = results;
+      }
+    }
+
+    protected virtual void FlpSolverEvaluationPortMessage(IMessage message) { }
+    #endregion
+
+    #region VrpSolver Message Handling
+    protected virtual void VrpSolverOrchestrationPortMessage(IMessage message) {
+      var results = (ResultCollection)message["Results"];
+      if (results.ContainsKey("Best valid VRP Solution")) {
+        vrpResults = results;
+      }
+    }
+
+    private void VrpSolverEvaluationPortMessage(IMessage message) { }
+    #endregion
+  }
+}
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode1.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode1.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode1.cs	(revision 14621)
@@ -21,23 +21,15 @@
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
-using System.Text.RegularExpressions;
-using System.Threading;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Core.Networks;
 using HeuristicLab.Data;
-using HeuristicLab.Encodings.BinaryVectorEncoding;
 using HeuristicLab.Encodings.IntegerVectorEncoding;
-using HeuristicLab.Encodings.PermutationEncoding;
 using HeuristicLab.Encodings.RealVectorEncoding;
-using HeuristicLab.Operators;
 using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.FacilityLocation;
 using HeuristicLab.Problems.VehicleRouting;
-using HeuristicLab.Problems.VehicleRouting.Encodings.General;
 using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
 
@@ -45,102 +37,14 @@
   [Item("LrpOrchestratorNode1", "Orchestrator for LRP optimization network version 1.")]
   [StorableClass]
-  public sealed class LrpOrchestratorNode1 : OrchestratorNode {
-    #region Constants
-    private const string InstanceParameterName = "Instance";
-    private const string FlpParameterName = "FLP";
-    private const string VrpParameterName = "VRP";
-    private const string MetaSolverName = "MetaSolver";
-    private const string FlpSolverName = "FlpSolver";
-    private const string VrpSolverName = "VrpSolver";
-    #endregion
-
-    private CancellationTokenSource cts;
-    private ResultCollection vrpResults, flpResults;
-
-    [Storable]
-    int nrOfDepots, nrOfCustomers;
-    [Storable]
-    double[,] depotCoordinates = new double[0, 0], customerCoordinates = new double[0, 0];
-    [Storable]
-    LrpUtils.DistanceType distanceType;
-    [Storable]
-    double[] depotCapacities = new double[0], customerDemands = new double[0], depotCosts = new double[0];
-    [Storable]
-    double vehicleCapacity, vehicleCost;
-
-    #region Parameters
-    public IFixedValueParameter<TextFileValue> InstanceParameter {
-      get { return (IFixedValueParameter<TextFileValue>)Parameters[InstanceParameterName]; }
-    }
-
-    public IValueParameter<FacilityLocationProblem> FlpParameter {
-      get { return (IValueParameter<FacilityLocationProblem>)Parameters[FlpParameterName]; }
-    }
-
-    public IValueParameter<VehicleRoutingProblem> VrpParameter {
-      get { return (IValueParameter<VehicleRoutingProblem>)Parameters[VrpParameterName]; }
-    }
-    #endregion
-
-    #region Ports
-    public IMessagePort MetaSolverOrchestrationPort {
-      get { return (IMessagePort)Ports[MetaSolverName + OrchestrationPortNameSuffix]; }
-    }
-
-    public IMessagePort MetaSolverEvaluationPort {
-      get { return (IMessagePort)Ports[MetaSolverName + EvaluationPortNameSuffix]; }
-    }
-
-    public IMessagePort FlpSolverOrchestrationPort {
-      get { return (IMessagePort)Ports[FlpSolverName + OrchestrationPortNameSuffix]; }
-    }
-
-    public IMessagePort FlpSolverEvaluationPort {
-      get { return (IMessagePort)Ports[FlpSolverName + EvaluationPortNameSuffix]; }
-    }
-
-    public IMessagePort VrpSolverOrchestrationPort {
-      get { return (IMessagePort)Ports[VrpSolverName + OrchestrationPortNameSuffix]; }
-    }
-
-    public IMessagePort VrpSolverEvaluationPort {
-      get { return (IMessagePort)Ports[VrpSolverName + EvaluationPortNameSuffix]; }
-    }
-    #endregion
-
+  public sealed class LrpOrchestratorNode1 : LrpOrchestratorNode {
     [StorableConstructor]
     private LrpOrchestratorNode1(bool deserializing) : base(deserializing) { }
-    private LrpOrchestratorNode1(LrpOrchestratorNode1 original, Cloner cloner) : base(original, cloner) {
-      nrOfDepots = original.nrOfDepots;
-      nrOfCustomers = original.nrOfCustomers;
-      depotCoordinates = (double[,])original.depotCoordinates.Clone();
-      customerCoordinates = (double[,])original.customerCoordinates.Clone();
-      distanceType = original.distanceType;
-      depotCapacities = (double[])original.depotCapacities.Clone();
-      customerDemands = (double[])original.customerDemands.Clone();
-      depotCosts = (double[])original.depotCosts.Clone();
-      vehicleCapacity = original.vehicleCapacity;
-      vehicleCost = original.vehicleCost;
-
-      RegisterEvents();
-    }
+    private LrpOrchestratorNode1(LrpOrchestratorNode1 original, Cloner cloner) : base(original, cloner) { }
     public LrpOrchestratorNode1() : this("LrpOrchestratorNode1") { }
     public LrpOrchestratorNode1(string name) : base(name) {
-      #region Configure Parameters
-      Parameters.Add(new FixedValueParameter<TextFileValue>(InstanceParameterName));
-      Parameters.Add(new ValueParameter<FacilityLocationProblem>(FlpParameterName, new FacilityLocationProblem()));
-      Parameters.Add(new ValueParameter<VehicleRoutingProblem>(VrpParameterName, new VehicleRoutingProblem() { ProblemInstance = new CVRPProblemInstance() }));
-      #endregion
-
-      #region Configure Ports
-      Ports.Add(CreateOrchestrationPort<VariegationProblem>(MetaSolverName));
-      Ports.Add(CreateEvaluationPort<RealVector>(MetaSolverName, "RealVector", "Quality"));
-      Ports.Add(CreateOrchestrationPort<VehicleRoutingProblem>(VrpSolverName));
-      Ports.Add(CreateEvaluationPort<Permutation>(VrpSolverName, "TSPTour", "TSPTourLength"));
-      Ports.Add(CreateOrchestrationPort<FacilityLocationProblem>(FlpSolverName));
-      Ports.Add(CreateEvaluationPort<BinaryVector>(FlpSolverName, "KnapsackSolution", "Quality"));
-
-      RegisterEvents();
-      #endregion
+      MetaSolverOrchestrationPort = CreateOrchestrationPort<VariegationProblem>(MetaSolverName);
+      MetaSolverEvaluationPort = CreateEvaluationPort<RealVector>(MetaSolverName, "RealVector", "Quality");
+      FlpSolverOrchestrationPort = CreateOrchestrationPort<FacilityLocationProblem>(FlpSolverName);
+      VrpSolverOrchestrationPort = CreateOrchestrationPort<VehicleRoutingProblem>(VrpSolverName);
     }
 
@@ -149,48 +53,6 @@
     }
 
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      RegisterEvents();
-    }
-
-    private void RegisterEvents() {
-      InstanceParameter.Value.ToStringChanged += InstanceParameter_Value_ToStringChanged;
-      MetaSolverOrchestrationPort.ConnectedPortChanged += MetaSolverOrchestrationPort_ConnectedPortChanged;
-      VrpSolverOrchestrationPort.ConnectedPortChanged += VrpSolverOrchestrationPort_ConnectedPortChanged;
-      FlpSolverOrchestrationPort.ConnectedPortChanged += FlpSolverOrchestrationPort_ConnectedPortChanged;
-    }
-
-    private void InstanceParameter_Value_ToStringChanged(object sender, EventArgs e) {
-      string filePath = InstanceParameter.Value.Value;
-      LrpUtils.Import(filePath, out nrOfDepots, out nrOfCustomers,
-                                out depotCoordinates, out customerCoordinates,
-                                out distanceType,
-                                out depotCapacities, out customerDemands, out depotCosts,
-                                out vehicleCapacity, out vehicleCost);
-
-      var flp = FlpParameter.Value;
-      flp.CustomerDemandsParameter.Value = new DoubleArray(customerDemands);
-      flp.DeliveryCostsParameter.Value = new DoubleMatrix(LrpUtils.GetFlpDeliveryCosts(depotCoordinates, customerCoordinates, distanceType));
-      flp.DepotCapacitiesParameter.Value = new DoubleArray(depotCapacities);
-      flp.Encoding.Length = nrOfCustomers;
-      flp.OpeningCostsParameter.Value = new DoubleArray(depotCosts);
-
-      var vrpInstance = (CVRPProblemInstance)VrpParameter.Value.ProblemInstance;
-      vrpInstance.Capacity.Value = vehicleCapacity;
-      vrpInstance.FleetUsageFactor.Value = vehicleCost;
-      vrpInstance.OverloadPenalty.Value = vehicleCost * 1000.0;
-
-      var crossover = VrpParameter.Value.OperatorsParameter.Value.OfType<MultiVRPSolutionCrossover>().Single(x => x.Name == "MultiVRPSolutionCrossover");
-      foreach (var c in crossover.Operators)
-        crossover.Operators.SetItemCheckedState(c, c.Name.StartsWith("Potvin"));
-      var mutator = VrpParameter.Value.OperatorsParameter.Value.OfType<MultiVRPSolutionManipulator>().Single(x => x.Name == "MultiVRPSolutionManipulator");
-      foreach (var m in mutator.Operators)
-        mutator.Operators.SetItemCheckedState(m, Regex.IsMatch(m.Name, @"Potvin(One|Two).*"));
-
-      Prepare();
-    }
-
     public override void Prepare(bool clearRuns = false) {
-      Results.Clear();
+      base.Prepare(clearRuns);
 
       var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
@@ -199,68 +61,12 @@
       metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(msgFlags);
       var problem = new VariegationProblem();
-      problem.Encoding.Length = FlpParameter.Value.Encoding.Length * 2;
-      problem.Encoding.Bounds = new DoubleMatrix(new[,] { { 0.0, 2.0 } });
+      problem.Encoding.Length = nrOfCustomers * 2;
+      problem.Encoding.Bounds = new DoubleMatrix(new[,] { { -1.0, 1.0 } });
       metaMsg["Problem"] = problem;
       MetaSolverOrchestrationPort.SendMessage(metaMsg);
     }
 
-    public override void Start() {
-      cts = new CancellationTokenSource();
-
-      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
-      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Start);
-      MetaSolverOrchestrationPort.SendMessage(metaMsg);
-    }
-
-    public override void Pause() {
-      cts.Cancel();
-
-      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
-      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Pause);
-      MetaSolverOrchestrationPort.SendMessage(metaMsg);
-
-      var vrpMsg = VrpSolverOrchestrationPort.PrepareMessage();
-      vrpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
-      VrpSolverOrchestrationPort.SendMessage(vrpMsg);
-
-      var kspMsg = FlpSolverOrchestrationPort.PrepareMessage();
-      kspMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
-      FlpSolverOrchestrationPort.SendMessage(kspMsg);
-    }
-
-    public override void Stop() {
-      cts.Cancel();
-
-      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
-      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
-      MetaSolverOrchestrationPort.SendMessage(metaMsg);
-
-      var vrpMsg = VrpSolverOrchestrationPort.PrepareMessage();
-      vrpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
-      VrpSolverOrchestrationPort.SendMessage(vrpMsg);
-
-      var kspMsg = FlpSolverOrchestrationPort.PrepareMessage();
-      kspMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Stop);
-      FlpSolverOrchestrationPort.SendMessage(kspMsg);
-    }
-
-    protected override void ProcessMessage(IMessage message, IMessagePort port, CancellationToken token) {
-      var messageActions = new Dictionary<IMessagePort, Action<IMessage>>();
-      messageActions.Add(MetaSolverOrchestrationPort, MetaSolverOrchestrationPortMessage);
-      messageActions.Add(MetaSolverEvaluationPort, MetaSolverEvaluationPortMessage);
-      messageActions.Add(VrpSolverOrchestrationPort, VrpSolverOrchestrationPortMessage);
-      messageActions.Add(VrpSolverEvaluationPort, VrpSolverEvaluationPortMessage);
-      messageActions.Add(FlpSolverOrchestrationPort, FlpSolverOrchestrationPortMessage);
-      messageActions.Add(FlpSolverEvaluationPort, FlpSolverEvaluationPortMessage);
-
-      messageActions[port](message);
-
-      base.ProcessMessage(message, port, token);
-    }
-
     #region MetaSolver Message Handling
-    private void MetaSolverOrchestrationPortMessage(IMessage message) { }
-
-    private void MetaSolverEvaluationPortMessage(IMessage message) {
+    protected override void MetaSolverEvaluationPortMessage(IMessage message) {
       var factors = (RealVector)message["RealVector"];
 
@@ -324,76 +130,4 @@
     }
     #endregion
-
-    #region VrpSolver Message Handling
-    private void VrpSolverOrchestrationPortMessage(IMessage message) {
-      var results = (ResultCollection)message["Results"];
-      if (results.ContainsKey("Best valid VRP Solution")) {
-        vrpResults = results;
-      }
-    }
-
-    private void VrpSolverEvaluationPortMessage(IMessage message) { }
-    #endregion
-
-    #region KspSolver Message Handling
-    private void FlpSolverOrchestrationPortMessage(IMessage message) {
-      var results = (ResultCollection)message["Results"];
-      if (results.ContainsKey("Best Solution")) {
-        flpResults = results;
-      }
-    }
-
-    private void FlpSolverEvaluationPortMessage(IMessage message) { }
-    #endregion
-
-    #region Event Handlers
-    private void MetaSolverOrchestrationPort_ConnectedPortChanged(object sender, EventArgs e) {
-      if (MetaSolverOrchestrationPort.ConnectedPort == null) return;
-
-      var node = MetaSolverOrchestrationPort.ConnectedPort.Parent as OrchestratedAlgorithmNode;
-      if (node == null) return;
-
-      var hook = new HookOperator { Name = "Meta Eval Hook" };
-      hook.Parameters.Add(new LookupParameter<RealVector>("RealVector") { Hidden = true });
-      hook.Parameters.Add(new LookupParameter<DoubleValue>("Quality") { Hidden = true });
-      node.EvalHook = hook;
-
-      node.OrchestrationPort.CloneParametersFromPort(MetaSolverOrchestrationPort);
-      node.EvaluationPort.CloneParametersFromPort(MetaSolverEvaluationPort);
-      node.EvaluationPort.ConnectedPort = MetaSolverEvaluationPort;
-    }
-
-    private void VrpSolverOrchestrationPort_ConnectedPortChanged(object sender, EventArgs e) {
-      if (VrpSolverOrchestrationPort.ConnectedPort == null) return;
-
-      var node = VrpSolverOrchestrationPort.ConnectedPort.Parent as OrchestratedAlgorithmNode;
-      if (node == null) return;
-
-      var hook = new HookOperator { Name = "VRP Eval Hook" };
-      hook.Parameters.Add(new LookupParameter<Permutation>("VRPTours") { Hidden = true });
-      hook.Parameters.Add(new LookupParameter<DoubleValue>("Quality") { Hidden = true });
-      node.EvalHook = hook;
-
-      node.OrchestrationPort.CloneParametersFromPort(VrpSolverOrchestrationPort);
-      node.EvaluationPort.CloneParametersFromPort(VrpSolverEvaluationPort);
-      node.EvaluationPort.ConnectedPort = VrpSolverEvaluationPort;
-    }
-
-    private void FlpSolverOrchestrationPort_ConnectedPortChanged(object sender, EventArgs e) {
-      if (FlpSolverOrchestrationPort.ConnectedPort == null) return;
-
-      var node = FlpSolverOrchestrationPort.ConnectedPort.Parent as OrchestratedAlgorithmNode;
-      if (node == null) return;
-
-      var hook = new HookOperator { Name = "FLP Eval Hook" };
-      hook.Parameters.Add(new LookupParameter<BinaryVector>("IntegerVector") { Hidden = true });
-      hook.Parameters.Add(new LookupParameter<DoubleValue>("Quality") { Hidden = true });
-      node.EvalHook = hook;
-
-      node.OrchestrationPort.CloneParametersFromPort(FlpSolverOrchestrationPort);
-      node.EvaluationPort.CloneParametersFromPort(FlpSolverEvaluationPort);
-      node.EvaluationPort.ConnectedPort = FlpSolverEvaluationPort;
-    }
-    #endregion
   }
 }
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode2.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode2.cs	(revision 14621)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.LocationRouting/3.3/LrpOrchestratorNode2.cs	(revision 14621)
@@ -0,0 +1,133 @@
+﻿#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.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Core.Networks;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.FacilityLocation;
+using HeuristicLab.Problems.VehicleRouting;
+using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
+
+namespace HeuristicLab.Networks.IntegratedOptimization.LocationRouting {
+  [Item("LrpOrchestratorNode2", "Orchestrator for LRP optimization network version 2.")]
+  [StorableClass]
+  public sealed class LrpOrchestratorNode2 : LrpOrchestratorNode {
+    [StorableConstructor]
+    private LrpOrchestratorNode2(bool deserializing) : base(deserializing) { }
+    private LrpOrchestratorNode2(LrpOrchestratorNode2 original, Cloner cloner) : base(original, cloner) { }
+    public LrpOrchestratorNode2() : this("LrpOrchestratorNode2") { }
+    public LrpOrchestratorNode2(string name) : base(name) {
+      MetaSolverOrchestrationPort = CreateOrchestrationPort<VariegationProblem>(MetaSolverName);
+      MetaSolverEvaluationPort = CreateEvaluationPort<RealVector>(MetaSolverName, "RealVector", "Quality");
+      FlpSolverOrchestrationPort = CreateOrchestrationPort<FacilityLocationProblem>(FlpSolverName);
+      VrpSolverOrchestrationPort = CreateOrchestrationPort<VehicleRoutingProblem>(VrpSolverName);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LrpOrchestratorNode2(this, cloner);
+    }
+
+    public override void Prepare(bool clearRuns = false) {
+      base.Prepare(clearRuns);
+
+      var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
+      var msgFlags = OrchestrationMessage.Prepare | OrchestrationMessage.SetEvalHook;
+      if (clearRuns) msgFlags |= OrchestrationMessage.ClearRuns;
+      metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(msgFlags);
+      var problem = new VariegationProblem();
+      problem.Encoding.Length = nrOfDepots * 2;
+      problem.Encoding.Bounds = new DoubleMatrix(new[,] { { -1.0, 1.0 } });
+      metaMsg["Problem"] = problem;
+      MetaSolverOrchestrationPort.SendMessage(metaMsg);
+    }
+
+    #region MetaSolver Message Handling
+    protected override void MetaSolverEvaluationPortMessage(IMessage message) {
+      var factors = (RealVector)message["RealVector"];
+
+      var flp = (FacilityLocationProblem)FlpParameter.Value.Clone();
+      var dc = (double[,])depotCoordinates.Clone();
+      for (int i = 0; i < nrOfDepots; i++) {
+        dc[i, 0] = dc[i, 0] * factors[i * 2];
+        dc[i, 1] = dc[i, 1] * factors[i * 2 + 1];
+      }
+      flp.DeliveryCostsParameter.Value = new DoubleMatrix(LrpUtils.GetFlpDeliveryCosts(dc, customerCoordinates, distanceType));
+
+      var flpMsg = FlpSolverOrchestrationPort.PrepareMessage();
+      flpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Prepare | OrchestrationMessage.ClearRuns | OrchestrationMessage.Start);
+      flpMsg["Problem"] = flp;
+      FlpSolverOrchestrationPort.SendMessage(flpMsg);
+      cts.Token.ThrowIfCancellationRequested();
+
+      var bestFlpSolution = (IntegerVector)flpResults["Best Solution"].Value;
+      var flpSolution = FlpParameter.Value.GetSolution(bestFlpSolution);
+
+      var depots = bestFlpSolution.Select((x, i) => Tuple.Create(x, i)).GroupBy(x => x.Item1, x => x.Item2);
+      var vrpSolutions = new ResultCollection(depots.Count());
+      foreach (var depot in depots.OrderBy(x => x.Key)) {
+        var depotIdx = depot.Key;
+        var customers = depot.ToArray();
+
+        var vrp = (VehicleRoutingProblem)VrpParameter.Value.Clone();
+        var vrpInstance = (CVRPProblemInstance)vrp.ProblemInstance;
+        var coordinates = LrpUtils.GetVrpCoordinates(depotCoordinates, customerCoordinates, depotIdx, customers);
+        var distances = LrpUtils.GetVrpDistances(coordinates, distanceType);
+        vrpInstance.Coordinates = new DoubleMatrix(coordinates);
+        vrpInstance.DistanceMatrix = new DoubleMatrix(distances);
+        vrpInstance.Demand = new DoubleArray(new[] { 0.0 }.Concat(customers.Select(x => customerDemands[x])).ToArray());
+        vrpInstance.Vehicles.Value = customers.Length;
+
+        var vrpMsg = VrpSolverOrchestrationPort.PrepareMessage();
+        vrpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Prepare | OrchestrationMessage.ClearRuns | OrchestrationMessage.Start);
+        vrpMsg["Problem"] = vrp;
+        VrpSolverOrchestrationPort.SendMessage(vrpMsg);
+        cts.Token.ThrowIfCancellationRequested();
+
+        var bestVrpSolution = (VRPSolution)vrpResults["Best valid VRP Solution"].Value.Clone();
+        vrpSolutions.Add(new Result("Depot " + depot.Key, bestVrpSolution));
+      }
+
+      #region Analyze
+      double objectiveValue = LrpUtils.Evaluate(flpSolution, vrpSolutions.Select(x => (VRPSolution)x.Value).ToArray());
+      ((DoubleValue)message["Quality"]).Value = objectiveValue;
+
+      IResult bestQuality;
+      if (!Results.TryGetValue("Best LRP Quality", out bestQuality)) {
+        Results.Add(new Result("Best LRP Quality", new DoubleValue(objectiveValue)));
+        Results.Add(new Result("Best FLP Solution", flpSolution));
+        Results.Add(new Result("Best VRP Solutions", vrpSolutions));
+      } else if (objectiveValue < ((DoubleValue)bestQuality.Value).Value) {
+        ((DoubleValue)bestQuality.Value).Value = objectiveValue;
+        Results["Best FLP Solution"].Value = flpSolution;
+        Results["Best VRP Solutions"].Value = vrpSolutions;
+      }
+      #endregion
+    }
+    #endregion
+  }
+}
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork.cs	(revision 14621)
@@ -31,5 +31,5 @@
   [Item("TtpNetwork", "An abstract base class for TTP optimization networks.")]
   [StorableClass]
-  public abstract class TtpNetwork : Network {
+  public abstract class TtpNetwork : Network, IOptimizer {
     #region Constants
     protected const string OrchestratorNodeName = "Orchestrator";
@@ -104,11 +104,11 @@
       if (algorithm == null) return;
 
-      algorithm.ExecutionStateChanged += OnExecutionStateChanged;
-      algorithm.ExecutionTimeChanged += OnExecutionTimeChanged;
-      algorithm.Prepared += OnPrepared;
-      algorithm.Started += OnStarted;
-      algorithm.Paused += OnPaused;
-      algorithm.Stopped += OnStopped;
-      algorithm.ExceptionOccurred += OnExceptionOccurred;
+      algorithm.ExecutionStateChanged += (s, e) => OnExecutionStateChanged();
+      algorithm.ExecutionTimeChanged += (s, e) => OnExecutionTimeChanged();
+      algorithm.Prepared += (s, e) => OnPrepared();
+      algorithm.Started += (s, e) => OnStarted();
+      algorithm.Paused += (s, e) => OnPaused();
+      algorithm.Stopped += (s, e) => OnStopped();
+      algorithm.ExceptionOccurred += (s, e) => OnExceptionOccurred(e.Value);
     }
 
@@ -167,12 +167,4 @@
     }
     #endregion
-
-    protected void OnExecutionStateChanged(object sender, EventArgs e) { OnExecutionStateChanged(); }
-    protected void OnExecutionTimeChanged(object sender, EventArgs e) { OnExecutionTimeChanged(); }
-    protected void OnPrepared(object sender, EventArgs e) { OnPrepared(); }
-    protected void OnStarted(object sender, EventArgs e) { OnStarted(); }
-    protected void OnPaused(object sender, EventArgs e) { OnPaused(); }
-    protected void OnStopped(object sender, EventArgs e) { OnStopped(); }
-    protected void OnExceptionOccurred(object sender, EventArgs<Exception> e) { OnExceptionOccurred(e.Value); }
   }
 }
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork1.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork1.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork1.cs	(revision 14621)
@@ -25,5 +25,4 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -32,5 +31,5 @@
   [Creatable("Optimization Networks")]
   [StorableClass]
-  public sealed class TtpNetwork1 : TtpNetwork, IOptimizer {
+  public sealed class TtpNetwork1 : TtpNetwork {
     [StorableConstructor]
     private TtpNetwork1(bool deserializing) : base(deserializing) { }
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork2.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork2.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork2.cs	(revision 14621)
@@ -25,5 +25,4 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -32,5 +31,5 @@
   [Creatable("Optimization Networks")]
   [StorableClass]
-  public sealed class TtpNetwork2 : TtpNetwork, IOptimizer {
+  public sealed class TtpNetwork2 : TtpNetwork {
     [StorableConstructor]
     private TtpNetwork2(bool deserializing) : base(deserializing) { }
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork3.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork3.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpNetwork3.cs	(revision 14621)
@@ -25,5 +25,4 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -32,5 +31,5 @@
   [Creatable("Optimization Networks")]
   [StorableClass]
-  public sealed class TtpNetwork3 : TtpNetwork, IOptimizer {
+  public sealed class TtpNetwork3 : TtpNetwork {
     [StorableConstructor]
     private TtpNetwork3(bool deserializing) : base(deserializing) { }
Index: /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpOrchestratorNode.cs
===================================================================
--- /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpOrchestratorNode.cs	(revision 14620)
+++ /branches/OptimizationNetworks/HeuristicLab.Networks.IntegratedOptimization.TravelingThief/3.3/TtpOrchestratorNode.cs	(revision 14621)
@@ -199,5 +199,5 @@
     }
 
-    protected void InstanceParameter_Value_ToStringChanged(object sender, EventArgs e) {
+    private void InstanceParameter_Value_ToStringChanged(object sender, EventArgs e) {
       string filePath = InstanceParameter.Value.Value;
       TtpUtils.Import(filePath, out tspCoordinates, out distanceType,
