Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Crossovers/MRCPSPTwoPointCrossover.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Crossovers/MRCPSPTwoPointCrossover.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Crossovers/MRCPSPTwoPointCrossover.cs	(revision 16598)
@@ -0,0 +1,150 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item("MRCPSP TwoPoint Crossover", "Applies two-point crossovers to cross a multi-encoding.")]
+  [StorableClass]
+  public sealed class MrcpspTwoPointCrossover : SingleSuccessorOperator, ICrossover, IStochasticOperator {
+
+    public MrcpspTwoPointCrossover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new ScopeTreeLookupParameter<RealVector>("RandomKeyParents", ""));
+      Parameters.Add(new ScopeTreeLookupParameter<IntegerVector>("ModeListParents", ""));
+      Parameters.Add(new LookupParameter<RealVector>("RandomKeyChild", ""));
+      Parameters.Add(new LookupParameter<IntegerVector>("ModeListChild", ""));
+    }
+
+    [StorableConstructor]
+    private MrcpspTwoPointCrossover(bool deserializing) : base(deserializing) { }
+
+    private MrcpspTwoPointCrossover(MrcpspTwoPointCrossover original, Cloner cloner) : base(original, cloner) {
+    }
+
+    public ILookupParameter<IntegerVector> ModeListChild => (ILookupParameter<IntegerVector>)Parameters["ModeListChild"];
+
+    public IScopeTreeLookupParameter<IntegerVector> ModeListParents => (IScopeTreeLookupParameter<IntegerVector>)Parameters["ModeListParents"];
+
+    public ILookupParameter<RealVector> RandomKeyChild => (ILookupParameter<RealVector>)Parameters["RandomKeyChild"];
+
+    public IScopeTreeLookupParameter<RealVector> RandomKeyParents =>
+      (IScopeTreeLookupParameter<RealVector>)Parameters["RandomKeyParents"];
+
+    public ILookupParameter<IRandom> RandomParameter => (ILookupParameter<IRandom>)Parameters["Random"];
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var length = RandomKeyParents.ActualValue[0].Length;
+      var breakpoint1 = random.Next(0, length);
+      var breakpoint2 = (breakpoint1 + random.Next(1, length)) % length;
+      var breakpoints = new[] { breakpoint1, breakpoint2 };
+      Array.Sort(breakpoints);
+
+      RandomKeyChild.ActualValue = Cross(RandomKeyParents.ActualValue, breakpoints);
+      ModeListChild.ActualValue = Cross(ModeListParents.ActualValue, breakpoints);
+
+      return base.Apply();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MrcpspTwoPointCrossover(this, cloner);
+    }
+
+    private static IntegerVector Cross(ItemArray<IntegerVector> parents, IReadOnlyList<int> breakpoints) {
+      var parent1 = parents.First();
+      var parent2 = parents.Last();
+      var length = parent1.Length;
+      var result = new int[length];
+
+      //perform crossover
+      var arrayIndex = 0;
+      var breakPointIndex = 0;
+      var firstParent = true;
+
+      while (arrayIndex < length) {
+        if (breakPointIndex < breakpoints.Count &&
+            arrayIndex == breakpoints[breakPointIndex]) {
+          breakPointIndex++;
+          firstParent = !firstParent;
+        }
+
+        result[arrayIndex] = firstParent ? parent1[arrayIndex] : parent2[arrayIndex];
+
+        arrayIndex++;
+      }
+
+      return new IntegerVector(result);
+    }
+
+    private static double Scale(double value, double min, double max, double newMin = 0.0, double newMax = 1.0) =>
+      (newMax - newMin) * (value - min) / (max - min) + newMin;
+
+    private static RealVector Scale(RealVector vector) {
+      var min = vector.Min();
+      var max = vector.Max();
+
+      var scaledVector = new RealVector(vector.Length);
+      for (var i = 0; i < vector.Length; i++) {
+        scaledVector[i] = Scale(vector[i], min, max);
+      }
+
+      return scaledVector;
+    }
+
+    private static RealVector Cross(ItemArray<RealVector> parents, IReadOnlyList<int> breakpoints) {
+      var parent1 = Scale(parents.First());
+      var parent2 = Scale(parents.Last());
+      var length = parent1.Length;
+      var result = new double[length];
+
+      //perform crossover
+      var arrayIndex = 0;
+      var breakPointIndex = 0;
+      var firstParent = true;
+
+      while (arrayIndex < length) {
+        if (breakPointIndex < breakpoints.Count &&
+            arrayIndex == breakpoints[breakPointIndex]) {
+          breakPointIndex++;
+          firstParent = !firstParent;
+        }
+
+        result[arrayIndex] = firstParent ? parent1[arrayIndex] : parent2[arrayIndex];
+
+        arrayIndex++;
+      }
+
+      return new RealVector(result);
+    }
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/Activity.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/Activity.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/Activity.cs	(revision 16598)
@@ -0,0 +1,82 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item(nameof(Activity), "")]
+  [StorableClass]
+  public sealed class Activity : ParameterizedNamedItem {
+    //public Activity()
+    //    : this() {
+    //}
+
+    public override string ToString() => $"{Name} (Activity {Number})";
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> numberParam;
+
+    [Storable]
+    private readonly IValueParameter<ItemList<Mode>> modesParam;
+
+    [Storable]
+    private readonly IValueParameter<ItemList<IntValue>> successorsParam;
+
+    public Activity() {
+      Parameters.Add(numberParam = new FixedValueParameter<IntValue>(nameof(Number), new IntValue()));
+      Parameters.Add(modesParam = new ValueParameter<ItemList<Mode>>(nameof(Modes), new ItemList<Mode>()));
+      Parameters.Add(successorsParam = new ValueParameter<ItemList<IntValue>>(nameof(Successors), new ItemList<IntValue>()));
+    }
+
+    [StorableConstructor]
+    private Activity(bool deserializing)
+        : base(deserializing) { }
+
+    private Activity(Activity original, Cloner cloner)
+        : base(original, cloner) {
+      numberParam = cloner.Clone(original.numberParam);
+      modesParam = cloner.Clone(original.modesParam);
+      successorsParam = cloner.Clone(original.successorsParam);
+    }
+
+    public int Number {
+      get => numberParam.Value.Value;
+      set => numberParam.Value.Value = value;
+    }
+
+    public ItemList<Mode> Modes {
+      get => modesParam.Value;
+      set => modesParam.Value = value;
+    }
+
+    public ItemList<IntValue> Successors {
+      get => successorsParam.Value;
+      set => successorsParam.Value = value;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) => new Activity(this, cloner);
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/Mode.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/Mode.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/Mode.cs	(revision 16598)
@@ -0,0 +1,61 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item(nameof(Mode), "")]
+  [StorableClass]
+  public sealed class Mode : ParameterizedNamedItem {
+    //public Mode()
+    //  : this() {
+    //}
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> durationParam;
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> numberParam;
+
+    [Storable]
+    private readonly IValueParameter<ItemList<ResourceDemand>> resourceDemandsParam;
+
+    public Mode() {
+      Parameters.Add(numberParam = new FixedValueParameter<IntValue>(nameof(Number), new IntValue()));
+      Parameters.Add(resourceDemandsParam = new ValueParameter<ItemList<ResourceDemand>>(nameof(ResourceDemands), new ItemList<ResourceDemand>()));
+      Parameters.Add(durationParam = new FixedValueParameter<IntValue>(nameof(Duration), new IntValue()));
+    }
+
+    [StorableConstructor]
+    private Mode(bool deserializing)
+      : base(deserializing) { }
+
+    private Mode(Mode original, Cloner cloner)
+      : base(original, cloner) {
+      numberParam = cloner.Clone(original.numberParam);
+      resourceDemandsParam = cloner.Clone(original.resourceDemandsParam);
+      durationParam = cloner.Clone(original.durationParam);
+    }
+
+    public int Duration {
+      get => durationParam.Value.Value;
+      set => durationParam.Value.Value = value;
+    }
+
+    public int Number {
+      get => numberParam.Value.Value;
+      set => numberParam.Value.Value = value;
+    }
+
+    public ItemList<ResourceDemand> ResourceDemands {
+      get => resourceDemandsParam.Value;
+      set => resourceDemandsParam.Value = value;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) => new Mode(this, cloner);
+
+    public override string ToString() => $"{Name} (Mode {Number})";
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/ResourceCapacity.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/ResourceCapacity.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/ResourceCapacity.cs	(revision 16598)
@@ -0,0 +1,61 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item(nameof(ResourceCapacity), "")]
+  [StorableClass]
+  public sealed class ResourceCapacity : ParameterizedNamedItem {
+    //public ResourceCapacity()
+    //  : this() {
+    //}
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> capacityParam;
+
+    [Storable]
+    private readonly IFixedValueParameter<BoolValue> isRenewableParam;
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> numberParam;
+
+    public ResourceCapacity() {
+      Parameters.Add(numberParam = new FixedValueParameter<IntValue>(nameof(Number), new IntValue()));
+      Parameters.Add(capacityParam = new FixedValueParameter<IntValue>(nameof(Capacity), new IntValue()));
+      Parameters.Add(isRenewableParam = new FixedValueParameter<BoolValue>(nameof(IsRenewable), new BoolValue()));
+    }
+
+    [StorableConstructor]
+    private ResourceCapacity(bool deserializing)
+      : base(deserializing) { }
+
+    public override string ToString() => $"{Name} (Resource {Number})";
+
+    private ResourceCapacity(ResourceCapacity original, Cloner cloner)
+      : base(original, cloner) {
+      numberParam = cloner.Clone(original.numberParam);
+      capacityParam = cloner.Clone(original.capacityParam);
+      isRenewableParam = cloner.Clone(original.isRenewableParam);
+    }
+
+    public int Capacity {
+      get => capacityParam.Value.Value;
+      set => capacityParam.Value.Value = value;
+    }
+
+    public bool IsRenewable {
+      get => isRenewableParam.Value.Value;
+      set => isRenewableParam.Value.Value = value;
+    }
+
+    public int Number {
+      get => numberParam.Value.Value;
+      set => numberParam.Value.Value = value;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) => new ResourceCapacity(this, cloner);
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/ResourceDemand.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/ResourceDemand.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Encoding/ResourceDemand.cs	(revision 16598)
@@ -0,0 +1,51 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item(nameof(ResourceDemand), "")]
+  [StorableClass]
+  public sealed class ResourceDemand : ParameterizedNamedItem {
+    //public ResourceDemand()
+    //  : this() {
+    //}
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> demandParam;
+
+    [Storable]
+    private readonly IFixedValueParameter<IntValue> numberParam;
+
+    public ResourceDemand() {
+      Parameters.Add(numberParam = new FixedValueParameter<IntValue>(nameof(Number), new IntValue()));
+      Parameters.Add(demandParam = new FixedValueParameter<IntValue>(nameof(Demand), new IntValue()));
+    }
+
+    public override string ToString() => $"{Name} (Resource {Number})";
+
+    [StorableConstructor]
+    private ResourceDemand(bool deserializing)
+      : base(deserializing) { }
+
+    private ResourceDemand(ResourceDemand original, Cloner cloner)
+      : base(original, cloner) {
+      numberParam = cloner.Clone(original.numberParam);
+      demandParam = cloner.Clone(original.demandParam);
+    }
+
+    public int Demand {
+      get => demandParam.Value.Value;
+      set => demandParam.Value.Value = value;
+    }
+
+    public int Number {
+      get => numberParam.Value.Value;
+      set => numberParam.Value.Value = value;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) => new ResourceDemand(this, cloner);
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/HeuristicLab.Problem.Scheduling.MRCPSP-3.3.csproj
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/HeuristicLab.Problem.Scheduling.MRCPSP-3.3.csproj	(revision 16597)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/HeuristicLab.Problem.Scheduling.MRCPSP-3.3.csproj	(revision 16598)
@@ -22,4 +22,5 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -38,6 +39,63 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Encodings.IntegerVectorEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Encodings.RealVectorEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Encodings.RealVectorEncoding-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Operators-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimizer-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Optimizer-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Parameters-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Parameters-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Persistence-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Persistence-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
       <HintPath>..\..\..\..\trunk\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Random-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.Random-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.SimSharp-3.0.11, Version=3.0.11.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\HeuristicLab.SimSharp-3.0.11.dll</HintPath>
+    </Reference>
+    <Reference Include="SimSharp-3.0.11, Version=3.0.11.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\bin\SimSharp-3.0.11.dll</HintPath>
     </Reference>
     <Reference Include="System" />
@@ -56,7 +114,20 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Encoding\Activity.cs" />
+    <Compile Include="Improvers\BasicMrcpspImprover.cs" />
+    <Compile Include="Improvers\CriticalPathImprover.cs" />
+    <Compile Include="Improvers\FeasibilityImprover.cs" />
+    <Compile Include="Improvers\MrcpspImprover.cs" />
+    <Compile Include="MultiModeFileImporter.cs" />
+    <Compile Include="Encoding\Mode.cs" />
+    <Compile Include="MultiModeResourceConstrainedProjectSchedulingProblem.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Encoding\ResourceCapacity.cs" />
+    <Compile Include="Encoding\ResourceDemand.cs" />
+    <Compile Include="Crossovers\MrcpspTwoPointCrossover.cs" />
+    <Compile Include="Improvers\WorkContentImprover.cs" />
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/BasicMrcpspImprover.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/BasicMrcpspImprover.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/BasicMrcpspImprover.cs	(revision 16598)
@@ -0,0 +1,161 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+  [Item("Feasibility Improvement Method (FIM) Improver", "Improves a solution by calling GetNeighbors and Evaluate of the corresponding problem definition.")]
+  [StorableClass]
+  public abstract class BasicMrcpspImprover : SingleSuccessorOperator, IImprovementOperator, IStochasticOperator {
+
+    public MultiModeResourceConstrainedProjectSchedulingProblem Problem { get; set; }
+    public ILookupParameter<IRandom> RandomParameter => (ILookupParameter<IRandom>)Parameters["Random"];
+
+    public ILookupParameter<IEncoding> EncodingParameter => (ILookupParameter<IEncoding>)Parameters["Encoding"];
+
+    public ILookupParameter<DoubleValue> QualityParameter => (ILookupParameter<DoubleValue>)Parameters["Quality"];
+
+    public ILookupParameter<BoolValue> MaximizationParameter => (ILookupParameter<BoolValue>)Parameters["Maximization"];
+
+    public IValueLookupParameter<IntValue> ImprovementAttemptsParameter => (IValueLookupParameter<IntValue>)Parameters["ImprovementAttempts"];
+
+    public IValueLookupParameter<IntValue> SampleSizeParameter => (IValueLookupParameter<IntValue>)Parameters["SampleSize"];
+
+    public ILookupParameter<IntValue> LocalEvaluatedSolutionsParameter => (ILookupParameter<IntValue>)Parameters["LocalEvaluatedSolutions"];
+
+    public Func<Individual, IRandom, double> EvaluateFunc { get; set; }
+
+    [StorableConstructor]
+    protected BasicMrcpspImprover(bool deserializing) : base(deserializing) { }
+
+    protected BasicMrcpspImprover(BasicMrcpspImprover original, Cloner cloner) : base(original, cloner) {
+      Problem = cloner.Clone(original.Problem);
+    }
+
+    protected BasicMrcpspImprover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
+      Parameters.Add(new LookupParameter<IEncoding>("Encoding", "An item that holds the problem's encoding."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of the parameter vector."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "Whether the problem should be minimized or maximized."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("ImprovementAttempts", "The number of improvement attempts the operator should perform.", new IntValue(100)));
+      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of samples to draw from the neighborhood function at maximum.", new IntValue(300)));
+      Parameters.Add(new LookupParameter<IntValue>("LocalEvaluatedSolutions", "The number of solution evaluations that have been performed."));
+    }
+
+    public override IOperation Apply() {
+      var random = RandomParameter.ActualValue;
+      var encoding = EncodingParameter.ActualValue;
+      var maximize = MaximizationParameter.ActualValue.Value;
+      var maxAttempts = ImprovementAttemptsParameter.ActualValue.Value;
+      var sampleSize = SampleSizeParameter.ActualValue.Value;
+      var individual = encoding.GetIndividual(ExecutionContext.Scope);
+      //var quality = QualityParameter.ActualValue?.Value ?? EvaluateFunc(individual, random);
+
+      var count = 0;
+      //for (var i = 0; i < maxAttempts; i++) {
+      //  Individual best = null;
+      //  var bestQuality = quality;
+      //  foreach (var neighbor in GetNeighborsFunc(individual, random).Take(sampleSize)) {
+      //    var q = EvaluateFunc(neighbor, random);
+      //    count++;
+      //    if (maximize && bestQuality > q || !maximize && bestQuality < q) continue;
+      //    best = neighbor;
+      //    bestQuality = q;
+      //  }
+      //  if (best == null) break;
+      //  individual = best;
+      //  quality = bestQuality;
+      //}
+
+      if (Problem.CalculateERR(individual) <= 0)
+        return base.Apply();
+
+      var randomKey = individual.RealVector("RandomKey");
+      var modeList = individual.IntegerVector("ModeList");
+
+      var activities = Problem.Activities.Skip(1).Reverse().Skip(1).Reverse().ToList();
+
+      var delta = new Dictionary<int, Dictionary<int, int>>();
+
+      var index = 0;
+      foreach (var a in activities) {
+        delta[a.Number] = new Dictionary<int, int>();
+
+        foreach (var m in a.Modes) {
+          var ml = new IntegerVector(modeList) { [index] = m.Number };
+          delta[a.Number][m.Number] = Measure(randomKey, ml);
+          count++;
+        }
+
+        index++;
+      }
+
+      var totalDelta = delta.Sum(a => a.Value.Sum(m => m.Value));
+      var deltas = new List<Tuple<int, int, int>>();
+      foreach (var a in delta.Keys) {
+        foreach (var m in delta[a].Keys) {
+          deltas.Add(Tuple.Create(delta[a][m], a, m));
+        }
+      }
+
+      var selectedQuality = random.NextDouble() * totalDelta;
+      index = 0;
+      var currentQuality = deltas[index].Item1;
+      while (currentQuality < selectedQuality) {
+        index++;
+        currentQuality += deltas[index].Item1;
+      }
+
+      individual.IntegerVector("ModeList")[activities.FindIndex(a => a.Number == deltas[index].Item2)] = deltas[index].Item3;
+      var quality = Problem.Evaluate(individual, random);
+
+      LocalEvaluatedSolutionsParameter.ActualValue = new IntValue(count);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+      //individual.CopyToScope(ExecutionContext.Scope);
+      foreach (var val in individual.Values)
+        SetScopeValue(val.Key, ExecutionContext.Scope, val.Value);
+
+      return base.Apply();
+    }
+
+    protected abstract int Measure(RealVector randomKey, IntegerVector modeList);
+
+    private static void SetScopeValue(string name, IScope scope, IItem value) {
+      if (scope == null) throw new ArgumentNullException(nameof(scope));
+      if (value == null) throw new ArgumentNullException(nameof(value));
+
+      if (!scope.Variables.ContainsKey(name)) scope.Variables.Add(new Variable(name, value));
+      else scope.Variables[name].Value = value;
+    }
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/CriticalPathImprover.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/CriticalPathImprover.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/CriticalPathImprover.cs	(revision 16598)
@@ -0,0 +1,50 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+  [Item("Critical Path Improver", "")]
+  [StorableClass]
+  public sealed class CriticalPathImprover : BasicMrcpspImprover {
+
+    [StorableConstructor]
+    private CriticalPathImprover(bool deserializing) : base(deserializing) { }
+
+    private CriticalPathImprover(CriticalPathImprover original, Cloner cloner) : base(original, cloner) {
+      Problem = cloner.Clone(original.Problem);
+    }
+
+    public CriticalPathImprover() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CriticalPathImprover(this, cloner);
+    }
+
+    protected override int Measure(RealVector randomKey, IntegerVector modeList) => Problem.CalculateCP(randomKey, modeList);
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/FeasibilityImprover.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/FeasibilityImprover.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/FeasibilityImprover.cs	(revision 16598)
@@ -0,0 +1,50 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+  [Item("Feasibility Improver", "")]
+  [StorableClass]
+  public sealed class FeasibilityImprover : BasicMrcpspImprover {
+
+    [StorableConstructor]
+    private FeasibilityImprover(bool deserializing) : base(deserializing) { }
+
+    private FeasibilityImprover(FeasibilityImprover original, Cloner cloner) : base(original, cloner) {
+      Problem = cloner.Clone(original.Problem);
+    }
+
+    public FeasibilityImprover() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FeasibilityImprover(this, cloner);
+    }
+
+    protected override int Measure(RealVector randomKey, IntegerVector modeList) => Problem.CalculateERR(randomKey, modeList);
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/MrcpspImprover.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/MrcpspImprover.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/MrcpspImprover.cs	(revision 16598)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item("MRCPSP Improver", "Improves a solution by calling all MRCPSP improvement operators.")]
+  [StorableClass]
+  public sealed class MrcpspImprover : SingleSuccessorOperator, IImprovementOperator {
+
+    public MrcpspImprover() {
+      Parameters.Add(new LookupParameter<ItemCollection<IItem>>("Operators", ""));
+    }
+
+    [StorableConstructor]
+    private MrcpspImprover(bool deserializing) : base(deserializing) { }
+
+    private MrcpspImprover(MrcpspImprover original, Cloner cloner) : base(original, cloner) {
+    }
+
+    public ILookupParameter<ItemCollection<IItem>> OperatorsParameter =>
+      (ILookupParameter<ItemCollection<IItem>>)Parameters["Operators"];
+
+    public override IOperation Apply() {
+      var operators = OperatorsParameter.ActualValue;
+      var operations = operators
+        .OfType<IImprovementOperator>()
+        .Where(o => !(o is MrcpspImprover))
+        .Select(op => ExecutionContext.CreateOperation(op));
+      return new OperationCollection(operations);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MrcpspImprover(this, cloner);
+    }
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/WorkContentImprover.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/WorkContentImprover.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Improvers/WorkContentImprover.cs	(revision 16598)
@@ -0,0 +1,50 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+  [Item("Work Content Improver", "")]
+  [StorableClass]
+  public sealed class WorkContentImprover : BasicMrcpspImprover {
+
+    [StorableConstructor]
+    private WorkContentImprover(bool deserializing) : base(deserializing) { }
+
+    private WorkContentImprover(WorkContentImprover original, Cloner cloner) : base(original, cloner) {
+      Problem = cloner.Clone(original.Problem);
+    }
+
+    public WorkContentImprover() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new WorkContentImprover(this, cloner);
+    }
+
+    protected override int Measure(RealVector randomKey, IntegerVector modeList) => Problem.CalculateWC(randomKey, modeList);
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeFileImporter.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeFileImporter.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeFileImporter.cs	(revision 16598)
@@ -0,0 +1,349 @@
+﻿using HeuristicLab.Core;
+using HeuristicLab.Data;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  public static class MultiModeFileImporter {
+
+    public static MultiModeResourceConstrainedProjectSchedulingProblem Import(string file) {
+      var bounds = new Dictionary<string, int> {
+        {"J501_3", 25},
+        {"J502_2", 25},
+        {"J502_3", 22},
+        {"J502_4", 24},
+        {"J502_5", 23},
+        {"J504_1", 19},
+        {"J504_5", 22},
+        {"J507_1", 44},
+        {"J507_2", 42},
+        {"J507_3", 41},
+        {"J507_4", 45},
+        {"J507_5", 41},
+        {"J508_1", 37},
+        {"J508_2", 31},
+        {"J508_3", 33},
+        {"J508_4", 34},
+        {"J508_5", 42},
+        {"J509_1", 32},
+        {"J509_2", 24},
+        {"J509_3", 26},
+        {"J509_4", 26},
+        {"J509_5", 28},
+        {"J5010_1", 26},
+        {"J5010_2", 34},
+        {"J5010_3", 26},
+        {"J5010_4", 27},
+        {"J5010_5", 35},
+        {"J5011_1", 25},
+        {"J5011_2", 28},
+        {"J5011_3", 28},
+        {"J5011_4", 24},
+        {"J5011_5", 29},
+        {"J5012_1", 26},
+        {"J5012_2", 30},
+        {"J5012_3", 23},
+        {"J5012_4", 25},
+        {"J5012_5", 25},
+        {"J5020_1", 30},
+        {"J5020_2", 26},
+        {"J5020_4", 25},
+        {"J5020_5", 25},
+        {"J5021_1", 18},
+        {"J5021_5", 17},
+        {"J5022_1", 20},
+        {"J5023_1", 17},
+        {"J5023_4", 16},
+        {"J5043_1", 65},
+        {"J5043_2", 64},
+        {"J5043_3", 68},
+        {"J5043_4", 52},
+        {"J5043_5", 64},
+        {"J5044_1", 47},
+        {"J5044_2", 41},
+        {"J5044_3", 50},
+        {"J5044_4", 49},
+        {"J5044_5", 46},
+        {"J5045_1", 46},
+        {"J5045_2", 34},
+        {"J5045_3", 39},
+        {"J5045_4", 36},
+        {"J5045_5", 44},
+        {"J5046_1", 42},
+        {"J5046_2", 41},
+        {"J5046_3", 45},
+        {"J5046_4", 31},
+        {"J5046_5", 39},
+        {"J5047_1", 36},
+        {"J5047_2", 40},
+        {"J5047_3", 42},
+        {"J5047_4", 39},
+        {"J5047_5", 39},
+        {"J5048_1", 35},
+        {"J5048_2", 40},
+        {"J5048_3", 29},
+        {"J5048_4", 34},
+        {"J5048_5", 41},
+        {"J5056_1", 35},
+        {"J5056_3", 34},
+        {"J5056_4", 34},
+        {"J5056_5", 38},
+        {"J5057_3", 31},
+        {"J5058_1", 34},
+        {"J5058_4", 28},
+        {"J5058_5", 28},
+        {"J5074_5", 57},
+        {"J5079_1", 73},
+        {"J5079_2", 82},
+        {"J5079_3", 73},
+        {"J5079_4", 68},
+        {"J5079_5", 80},
+        {"J5080_1", 72},
+        {"J5080_2", 68},
+        {"J5080_3", 82},
+        {"J5080_4", 72},
+        {"J5080_5", 70},
+        {"J5081_1", 63},
+        {"J5081_3", 57},
+        {"J5081_4", 64},
+        {"J5081_5", 53},
+        {"J5082_1", 59},
+        {"J5082_2", 60},
+        {"J5082_3", 56},
+        {"J5082_4", 67},
+        {"J5082_5", 54},
+        {"J5083_1", 49},
+        {"J5083_4", 56},
+        {"J5083_5", 62},
+        {"J5084_1", 51},
+        {"J5084_2", 57},
+        {"J5084_3", 60},
+        {"J5084_4", 59},
+        {"J5084_5", 57},
+        {"J5092_4", 60},
+        {"J5094_2", 60},
+        {"J5094_3", 45},
+        {"J5094_4", 43},
+        {"J5096_2", 48}
+      };
+
+      var instance = ParseMultiModeFile(file);
+      instance.UpperBound = bounds.TryGetValue(Path.GetFileNameWithoutExtension(file), out var bound) ? bound : -1;
+      return CreateProblem(instance);
+    }
+
+    private static MultiModeResourceConstrainedProjectSchedulingProblem CreateProblem(MMRCPSP instance) {
+      var problem = new MultiModeResourceConstrainedProjectSchedulingProblem { Name = instance.Name };
+
+      if (instance.UpperBound > -1) {
+        problem.BestKnownQuality = instance.UpperBound;
+      }
+
+      if (instance.NbTasks != instance.Tasks.Count)
+        throw new InvalidDataException();
+
+      foreach (var task in instance.Tasks) {
+        var activity = new Activity {
+          Number = task.TaskId
+        };
+
+        foreach (var succ in task.Successors) {
+          activity.Successors.Add(new IntValue(succ));
+        }
+
+        foreach (var mode in instance.Modes.Where(m => m.TaskId == task.TaskId)) {
+          var m = new MRCPSP.Mode {
+            Number = mode.ModeId,
+            Duration = mode.Duration
+          };
+
+          var num = 1;
+          foreach (var demand in mode.DemRenewableRsrc) {
+            if (demand == 0) {
+              num++;
+              continue;
+            }
+            m.ResourceDemands.Add(new ResourceDemand { Demand = demand, Number = num++ });
+          }
+
+          foreach (var demand in mode.DemNonRenewableRsrc) {
+            if (demand == 0) {
+              num++;
+              continue;
+            }
+            m.ResourceDemands.Add(new ResourceDemand { Demand = demand, Number = num++ });
+          }
+
+          activity.Modes.Add(m);
+        }
+
+        problem.Activities.Add(activity);
+      }
+
+      problem.ResourceCapacities = new ItemList<ResourceCapacity>();
+
+      var number = 1;
+      foreach (var cap in instance.CapRenewableRsrc) {
+        problem.ResourceCapacities.Add(new ResourceCapacity {
+          Name = $"R{number}",
+          Number = number++,
+          Capacity = cap,
+          IsRenewable = true
+        });
+      }
+
+      foreach (var cap in instance.CapNonRenewableRsrc) {
+        problem.ResourceCapacities.Add(new ResourceCapacity {
+          Name = $"N{number - instance.NbRenewableRsrcs}",
+          Number = number++,
+          Capacity = cap,
+          IsRenewable = false
+        });
+      }
+
+      problem.InitEncoding();
+      return problem;
+    }
+
+    private static MMRCPSP ParseMultiModeFile(string filePath) {
+      var result = new MMRCPSP {
+        Name = Path.GetFileNameWithoutExtension(filePath),
+        Tasks = new List<Task>(),
+        Modes = new List<Mode>()
+      };
+
+      var section = 0;
+      var prevJob = 0;
+
+      foreach (var line in File.ReadLines(filePath).Select(l => l.Trim())) {
+        if (string.IsNullOrEmpty(line))
+          continue;
+
+        if (line.StartsWith("RESOURCES")) {
+          section = 1;
+          continue;
+        }
+
+        if (line.StartsWith("PRECEDENCE RELATIONS")) {
+          section = 2;
+          continue;
+        }
+
+        if (line.StartsWith("REQUESTS/DURATIONS")) {
+          section = 3;
+          continue;
+        }
+
+        if (line.StartsWith("RESOURCE AVAILABILITIES") || line.StartsWith("RESOURCEAVAILABILITIES")) {
+          section = 4;
+          continue;
+        }
+
+        switch (section) {
+          case 0: // Jobs
+            if (line.StartsWith("jobs", StringComparison.InvariantCultureIgnoreCase)) {
+              result.NbTasks = int.Parse(Regex.Match(line, @":[ \t]*(?<jobs>\d+)").Groups["jobs"].Value);
+            }
+
+            break;
+
+          case 1: // Resources
+            if (line.StartsWith("- nonrenewable")) {
+              result.NbNonRenewableRsrcs = int.Parse(Regex.Match(line, @":.*(?<nr>\d+).*N").Groups["nr"].Value);
+              result.CapNonRenewableRsrc = new int[result.NbNonRenewableRsrcs];
+            } else if (line.StartsWith("- renewable")) {
+              result.NbRenewableRsrcs = int.Parse(Regex.Match(line, @":.*(?<nr>\d+).*R").Groups["nr"].Value);
+              result.CapRenewableRsrc = new int[result.NbRenewableRsrcs];
+            }
+
+            break;
+
+          case 2: // Precedence Relations
+            if (char.IsDigit(line[0])) {
+              var numbers = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
+              var task = new Task {
+                TaskId = int.Parse(numbers[0]),
+                Successors = new List<int>(numbers.Skip(3).Select(x => int.Parse(x)))
+              };
+              result.Tasks.Add(task);
+            }
+
+            break;
+
+          case 3: // Requests/Durations
+            if (char.IsDigit(line[0])) {
+              var numbers = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
+              var mode = new Mode {
+                DemRenewableRsrc = new int[result.NbRenewableRsrcs],
+                DemNonRenewableRsrc = new int[result.NbNonRenewableRsrcs]
+              };
+              var next = 0;
+              if (numbers.Length == 3 + result.NbRenewableRsrcs + result.NbNonRenewableRsrcs) {
+                prevJob = int.Parse(numbers[next++]);
+              }
+              mode.TaskId = prevJob;
+              mode.ModeId = int.Parse(numbers[next++]);
+              mode.Duration = int.Parse(numbers[next++]);
+              for (var i = 0; i < result.NbRenewableRsrcs; i++) {
+                mode.DemRenewableRsrc[i] = int.Parse(numbers[next++]);
+              }
+              for (var i = 0; i < result.NbNonRenewableRsrcs; i++) {
+                mode.DemNonRenewableRsrc[i] = int.Parse(numbers[next++]);
+              }
+              result.Modes.Add(mode);
+            }
+
+            break;
+
+          case 4: // Resource Availabilities
+            if (char.IsDigit(line[0])) {
+              var numbers = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
+              var next = 0;
+              for (var i = 0; i < result.NbRenewableRsrcs; i++) {
+                result.CapRenewableRsrc[i] = int.Parse(numbers[next++]);
+              }
+              for (var i = 0; i < result.NbNonRenewableRsrcs; i++) {
+                result.CapNonRenewableRsrc[i] = int.Parse(numbers[next++]);
+              }
+            }
+
+            break;
+
+          default: // unkown section
+            continue;
+        }
+      }
+
+      return result;
+    }
+
+    private class MMRCPSP {
+      public int[] CapNonRenewableRsrc;
+      public int[] CapRenewableRsrc;
+      public List<Mode> Modes;
+      public string Name;
+      public int NbNonRenewableRsrcs;
+      public int NbRenewableRsrcs;
+      public int NbTasks;
+      public List<Task> Tasks;
+      public int UpperBound;
+    }
+
+    private class Mode {
+      public int[] DemNonRenewableRsrc;
+      public int[] DemRenewableRsrc;
+      public int Duration;
+      public int ModeId;
+      public int TaskId;
+    }
+
+    private class Task {
+      public List<int> Successors;
+      public int TaskId;
+    }
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeResourceConstrainedProjectSchedulingProblem.cs
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeResourceConstrainedProjectSchedulingProblem.cs	(revision 16598)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeResourceConstrainedProjectSchedulingProblem.cs	(revision 16598)
@@ -0,0 +1,319 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using SimSharp;
+using Environment = SimSharp.Environment;
+using IRandom = HeuristicLab.Core.IRandom;
+
+namespace HeuristicLab.Problems.Scheduling.MRCPSP {
+
+  [Item("Multi-mode Resource-Constrained Project Scheduling Problem (MRCPSP)", "")]
+  [Creatable(CreatableAttribute.Categories.CombinatorialProblems)]
+  [StorableClass]
+  public sealed class MultiModeResourceConstrainedProjectSchedulingProblem : SingleObjectiveBasicProblem<MultiEncoding> {
+    //public MultiModeResourceConstrainedProjectSchedulingProblem()
+    //    : this() {
+    //}
+
+    [Storable] private readonly IValueParameter<ItemList<Activity>> activitiesParam;
+
+    [Storable] private readonly IValueParameter<ItemList<ResourceCapacity>> resourceCapacitiesParam;
+
+    public MultiModeResourceConstrainedProjectSchedulingProblem() {
+      Parameters.Add(activitiesParam =
+        new ValueParameter<ItemList<Activity>>(nameof(Activities), new ItemList<Activity>()));
+      Parameters.Add(resourceCapacitiesParam =
+        new ValueParameter<ItemList<ResourceCapacity>>(nameof(ResourceCapacities), new ItemList<ResourceCapacity>()));
+
+      Operators.Add(new MrcpspTwoPointCrossover {
+        RandomKeyParents = { ActualName = "RandomKey" },
+        ModeListParents = { ActualName = "ModeList" },
+        RandomKeyChild = { ActualName = "RandomKey" },
+        ModeListChild = { ActualName = "ModeList" }
+      });
+      Operators.Add(new MrcpspImprover());
+      Operators.Add(new FeasibilityImprover { Problem = this, EvaluateFunc = Evaluate });
+      Operators.Add(new WorkContentImprover { Problem = this, EvaluateFunc = Evaluate });
+      Operators.Add(new CriticalPathImprover { Problem = this, EvaluateFunc = Evaluate });
+    }
+
+    [StorableConstructor]
+    private MultiModeResourceConstrainedProjectSchedulingProblem(bool deserializing)
+      : base(deserializing) {
+    }
+
+    private MultiModeResourceConstrainedProjectSchedulingProblem(
+      MultiModeResourceConstrainedProjectSchedulingProblem original, Cloner cloner)
+      : base(original, cloner) {
+      activitiesParam = cloner.Clone(original.activitiesParam);
+      resourceCapacitiesParam = cloner.Clone(original.resourceCapacitiesParam);
+    }
+
+    public ItemList<Activity> Activities {
+      get => activitiesParam.Value;
+      set => activitiesParam.Value = value;
+    }
+
+    public override bool Maximization => false;
+
+    public ItemList<ResourceCapacity> ResourceCapacities {
+      get => resourceCapacitiesParam.Value;
+      set => resourceCapacitiesParam.Value = value;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) =>
+      new MultiModeResourceConstrainedProjectSchedulingProblem(this, cloner);
+
+    public void InitEncoding() {
+      var activities = Activities.Skip(1).Reverse().Skip(1).Reverse().ToList();
+
+      Encoding = new MultiEncoding();
+      Encoding.Add(new RealVectorEncoding("RandomKey", activities.Count, 0.0, 1.0));
+      Encoding.Add(new IntegerVectorEncoding("ModeList", activities.Count,
+        Enumerable.Repeat(1, activities.Count).ToList(), activities.Select(a => a.Modes.Count + 1).ToList()));
+    }
+
+    // work content
+    public int CalculateWC(RealVector randomKey, IntegerVector modeList) {
+      ExtractSolution(randomKey, modeList, out var activities, out _);
+
+      var workContent = 0;
+
+      foreach (var activity in activities) {
+        var mode = activity.Item1.Modes.Single(m => m.Number == activity.Item3);
+        workContent += mode.ResourceDemands.Where(d => IsRenewable(d.Number)).Sum(demand => demand.Demand);
+      }
+
+      return workContent;
+    }
+
+    public class CpActivity {
+      public int Id { get; set; }
+      public int Duration { get; set; }
+      public List<CpActivity> Predecessors { get; set; } = new List<CpActivity>();
+      public List<CpActivity> Successors { get; set; } = new List<CpActivity>();
+      public bool IsStartNode { get; set; }
+      public bool IsEndNode { get; set; }
+      public int EarliestStart { get; set; }
+      public int EarliestEnd { get; set; }
+      public int LatestStart { get; set; }
+      public int LatestEnd { get; set; }
+    }
+
+    public int GetCriticalPathLength(ref List<CpActivity> activities) {
+      ForwardScheduling(activities.First(x => x.IsStartNode));
+      var endNode = activities.First(x => x.IsEndNode);
+      return endNode.EarliestEnd;
+    }
+
+    public List<CpActivity> GetCriticalActivities(ref List<CpActivity> activities) {
+      ForwardScheduling(activities.First(x => x.IsStartNode));
+      var endNode = activities.First(x => x.IsEndNode);
+      endNode.LatestEnd = endNode.EarliestEnd;
+      endNode.LatestStart = endNode.LatestEnd - endNode.Duration;
+      BackwardScheduling(endNode);
+      return activities
+        .Where(a => a.EarliestEnd - a.LatestEnd == 0 && a.EarliestStart - a.LatestStart == 0)
+        .ToList();
+    }
+
+    private static void ForwardScheduling(CpActivity position) {
+      foreach (var successor in position.Successors) {
+        foreach (var predecessor in successor.Predecessors) {
+          if (successor.EarliestStart < predecessor.EarliestEnd)
+            successor.EarliestStart = predecessor.EarliestEnd;
+        }
+
+        successor.EarliestEnd = successor.EarliestStart + successor.Duration;
+      }
+
+      foreach (var successor in position.Successors) {
+        ForwardScheduling(successor);
+      }
+    }
+
+    private static void BackwardScheduling(CpActivity cpActivity) {
+      foreach (var predecessor in cpActivity.Predecessors) {
+        foreach (var successor in predecessor.Successors) {
+          if (predecessor.LatestEnd == 0) {
+            predecessor.LatestEnd = successor.LatestStart;
+          } else if (predecessor.LatestEnd > successor.LatestStart) {
+            predecessor.LatestEnd = successor.LatestStart;
+          }
+        }
+
+        predecessor.LatestStart = predecessor.LatestEnd - predecessor.Duration;
+      }
+
+      foreach (var predecessor in cpActivity.Predecessors) {
+        BackwardScheduling(predecessor);
+      }
+    }
+
+    public int CalculateCP(RealVector randomKey, IntegerVector modeList) {
+      ExtractSolution(randomKey, modeList, out var activities, out _);
+
+      var successors = activities.SelectMany(a => a.Item1.Successors.Select(s => s.Value));
+      var startNode = activities.Single(a => successors.All(s => s != a.Item1.Number)).Item1.Number;
+
+      var act = new List<CpActivity>();
+      foreach (var activity in activities) {
+        var a = activity.Item1;
+        var m = activity.Item1.Modes.Single(x => x.Number == activity.Item3);
+
+        act.Add(new CpActivity {
+          Id = a.Number,
+          Duration = m.Duration,
+          IsStartNode = a.Number == startNode,
+          IsEndNode = !a.Successors.Any()
+        });
+      }
+
+      foreach (var activity in activities) {
+        var a = activity.Item1;
+        var ax = act.Single(x => x.Id == a.Number);
+        foreach (var s in a.Successors) {
+          var sx = act.Single(x => x.Id == s.Value);
+          ax.Successors.Add(sx);
+          sx.Predecessors.Add(ax);
+        }
+      }
+
+      return GetCriticalPathLength(ref act);
+    }
+
+    public int CalculateERR(Individual individual)
+      => CalculateERR(individual.RealVector("RandomKey"), individual.IntegerVector("ModeList"));
+
+    // excess of resource request
+    public int CalculateERR(RealVector randomKey, IntegerVector modeList) {
+      ExtractSolution(randomKey, modeList, out var activities, out _);
+
+      var totalDemands = ResourceCapacities.Where(c => !c.IsRenewable).ToDictionary(c => c.Number, c => 0);
+
+      foreach (var activity in activities) {
+        var mode = activity.Item1.Modes.Single(m => m.Number == activity.Item3);
+        foreach (var demand in mode.ResourceDemands) {
+          if (totalDemands.ContainsKey(demand.Number))
+            totalDemands[demand.Number] += demand.Demand;
+        }
+      }
+
+      return totalDemands.Sum(d => Math.Max(0, d.Value - ResourceCapacities.Single(c => c.Number == d.Key).Capacity));
+    }
+
+    private void ExtractSolution(Individual individual, out List<Tuple<Activity, double, int>> activities,
+      out Dictionary<int, List<int>> dependencies)
+      => ExtractSolution(individual.RealVector("RandomKey"), individual.IntegerVector("ModeList"), out activities,
+        out dependencies);
+
+    private void ExtractSolution(RealVector randomKey, IntegerVector modeList, out List<Tuple<Activity, double, int>> activities, out Dictionary<int, List<int>> dependencies) {
+      activities = new List<Tuple<Activity, double, int>>(Activities.Count);
+      dependencies = new Dictionary<int, List<int>>(Activities.Count);
+
+      var act = Activities[0];
+      activities.Add(Tuple.Create(act, double.MinValue, act.Modes.First().Number));
+      dependencies[act.Number] = new List<int>();
+
+      for (var i = 1; i < Activities.Count - 1; i++) {
+        activities.Add(Tuple.Create(Activities[i], randomKey[i - 1], modeList[i - 1]));
+        dependencies[Activities[i].Number] = new List<int>();
+      }
+
+      act = Activities[Activities.Count - 1];
+      activities.Add(Tuple.Create(act, double.MaxValue, act.Modes.First().Number));
+      dependencies[act.Number] = new List<int>();
+
+      foreach (var activity in Activities) {
+        foreach (var successor in activity.Successors) {
+          dependencies[successor.Value].Add(activity.Number);
+        }
+      }
+
+      activities = activities.OrderBy(a => a.Item2).ToList();
+    }
+
+    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
+      var bestIndividual = GetBestIndividual(individuals, qualities, Maximization);
+      results.AddOrUpdateResult("BestSolution.RandomKey", bestIndividual.Item1.RealVector("RandomKey"));
+      results.AddOrUpdateResult("BestSolution.ModeList", bestIndividual.Item1.IntegerVector("ModeList"));
+      base.Analyze(individuals, qualities, results, random);
+    }
+
+    public override double Evaluate(Individual individual, IRandom random) {
+      ExtractSolution(individual, out var activities, out var dependencies);
+
+      var env = new Environment();
+      var procActivities = new Dictionary<int, Process>();
+
+      var resources = ResourceCapacities
+        .ToDictionary(resource => resource.Number, resource => new Container(env, resource.Capacity, resource.Capacity));
+
+      foreach (var activity in activities) {
+        procActivities[activity.Item1.Number] =
+          env.Process(Job(env, procActivities, activity, resources, dependencies[activity.Item1.Number]));
+      }
+
+      // fitness function by Hartmann (2001)
+      try {
+        env.Run();
+        return env.NowD;
+      } catch (InvalidOperationException) {
+        var T = Activities.Sum(a => a.Modes.Max(m => m.Duration));
+        return T + CalculateERR(individual);
+      }
+    }
+
+    private bool IsRenewable(int resourceNumber) => ResourceCapacities.Single(r => r.Number == resourceNumber).IsRenewable;
+
+    private IEnumerable<Event> Job(Environment env, IReadOnlyDictionary<int, Process> procActivities,
+      Tuple<Activity, double, int> activity, IReadOnlyDictionary<int, Container> resources, IEnumerable<int> deps) {
+      var mode = activity.Item1.Modes[activity.Item3 - 1];
+      var demands = mode.ResourceDemands.Where(d => d.Demand > 0).ToList();
+      var rres = demands.Where(d => IsRenewable(d.Number)).Select(d => Tuple.Create(resources[d.Number], d.Demand));
+      var nres = demands.Where(d => !IsRenewable(d.Number)).Select(d => Tuple.Create(resources[d.Number], d.Demand));
+
+      yield return new AllOf(env, deps.Select(d => procActivities[d]));
+
+      foreach (var nr in nres) {
+        if (nr.Item2 > nr.Item1.Level)
+          throw new InvalidOperationException();
+        yield return nr.Item1.Get(nr.Item2);
+      }
+
+      foreach (var rr in rres) {
+        yield return rr.Item1.Get(rr.Item2);
+        yield return env.TimeoutD(mode.Duration);
+        yield return rr.Item1.Put(rr.Item2);
+      }
+    }
+  }
+}
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Plugin.cs.frame
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Plugin.cs.frame	(revision 16597)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Plugin.cs.frame	(revision 16598)
@@ -1,8 +1,40 @@
-﻿using HeuristicLab.PluginInfrastructure;
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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.Problems.Scheduling.MRCPSP {
   [Plugin("HeuristicLab.Problems.Scheduling.MRCPSP", "3.3.15.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.Scheduling.MRCPSP-3.3.dll", PluginFileType.Assembly)]
-  public class Plugin : PluginBase {
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.IntegerVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+  [PluginDependency("HeuristicLab.SimSharp", "3.0.11")]
+  public class HeuristicLabMrspspPlugin : PluginBase {
   }
 }
Index: /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Properties/AssemblyInfo.cs.frame	(revision 16597)
+++ /branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/Properties/AssemblyInfo.cs.frame	(revision 16598)
@@ -1,3 +1,24 @@
-﻿using System.Reflection;
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2019 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;
 
@@ -10,5 +31,5 @@
 [assembly: AssemblyCompany("HEAL")]
 [assembly: AssemblyProduct("HeuristicLab")]
-[assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
+[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
Index: /branches/2981_MRCPSP/UnitTestProject/Properties/AssemblyInfo.cs
===================================================================
--- /branches/2981_MRCPSP/UnitTestProject/Properties/AssemblyInfo.cs	(revision 16598)
+++ /branches/2981_MRCPSP/UnitTestProject/Properties/AssemblyInfo.cs	(revision 16598)
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("UnitTestProject1")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("FH-Hagenberg")]
+[assembly: AssemblyProduct("UnitTestProject1")]
+[assembly: AssemblyCopyright("Copyright Â© FH-Hagenberg 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("717869df-eee7-4cb7-ae7e-80769c32c180")]
+
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
Index: /branches/2981_MRCPSP/UnitTestProject/UnitTest.cs
===================================================================
--- /branches/2981_MRCPSP/UnitTestProject/UnitTest.cs	(revision 16598)
+++ /branches/2981_MRCPSP/UnitTestProject/UnitTest.cs	(revision 16598)
@@ -0,0 +1,187 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.Scheduling.MRCPSP;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SimSharp;
+using Environment = SimSharp.Environment;
+
+namespace UnitTestProject {
+  [TestClass]
+  public class UnitTest {
+
+    [TestMethod]
+    public void Import() {
+      var problem = MultiModeFileImporter.Import(@"C:\Users\P41826\FH OÖ FileBox\MRCPSP\MRCPSP_BenchmarkData\mmlib 50\mmlib50.mm\J501_1.mm");
+    }
+
+    [TestMethod]
+    public void TestMethod1() {
+      Console.Write(Evaluate());
+    }
+
+    public ItemList<Activity> Activities { get; set; } = new ItemList<Activity>();
+    public ItemList<ResourceCapacity> ResourceCapacities { get; set; } = new ItemList<ResourceCapacity>();
+
+    public UnitTest() {
+
+      var RR = new ResourceCapacity { Number = 1, Capacity = 7, IsRenewable = true };
+      var RN = new ResourceCapacity { Number = 2, Capacity = 23, IsRenewable = false };
+
+      ResourceCapacities.Add(RR);
+      ResourceCapacities.Add(RN);
+
+
+      var A = new List<Tuple<int, int, int, int, int>>
+      {
+        Tuple.Create(1, 1, 4, 3, 3),
+        Tuple.Create(1, 2, 5, 2, 4),
+        Tuple.Create(2, 1, 1, 3, 4),
+        Tuple.Create(2, 2, 2, 2, 3),
+        Tuple.Create(3, 1, 1, 2, 3),
+        Tuple.Create(3, 2, 2, 1, 1),
+        Tuple.Create(4, 1, 2, 5, 4),
+        Tuple.Create(4, 2, 3, 4, 3),
+        Tuple.Create(5, 1, 2, 4, 6),
+        Tuple.Create(5, 2, 5, 3, 2),
+        Tuple.Create(6, 1, 1, 1, 4),
+        Tuple.Create(6, 2, 3, 1, 3),
+        Tuple.Create(7, 1, 1, 3, 3),
+        Tuple.Create(7, 2, 3, 2, 2),
+        Tuple.Create(8, 1, 2, 3, 4),
+        Tuple.Create(8, 2, 2, 3, 3)
+      };
+      var S = new Dictionary<int, List<int>>
+      {
+        {0, new List<int> {1, 2, 3}},
+        {1, new List<int> {7}},
+        {2, new List<int> {4, 5}},
+        {3, new List<int> {9}},
+        {4, new List<int> {6}},
+        {5, new List<int> {9}},
+        {6, new List<int> {7, 8}},
+        {7, new List<int> {9}},
+        {8, new List<int> {9}},
+        {9, new List<int>()}
+      };
+
+      Activities = new ItemList<Activity>(Enumerable.Range(0, 10).Select(i => new Activity { Number = i }).ToList());
+      Activities[0].Modes.Add(new Mode { Number = 1 });
+      foreach (var a in A) {
+        Activities[a.Item1].Modes.Add(new Mode {
+          Number = a.Item2,
+          Duration = a.Item3,
+          ResourceDemands = new ItemList<ResourceDemand>
+          {
+            new ResourceDemand {Number = 1, Demand = a.Item4},
+            new ResourceDemand {Number = 2, Demand = a.Item5}
+          }
+        });
+      }
+
+      Activities[9].Modes.Add(new Mode { Number = 1 });
+      foreach (var s in S) {
+        Activities[s.Key].Successors = new ItemList<IntValue>(s.Value.Select(x => new IntValue(x)));
+      }
+    }
+
+    public MultiEncoding Encoding { get; set; }
+
+    public double Evaluate() {
+      var randomKey = new IntegerVector(new[] { 1, 2, 3, 4, 5, 6, 7, 8 });
+      var modeList = new IntegerVector(new[] { 1, 1, 2, 2, 2, 1, 1, 2 });
+
+      var activities = new List<Tuple<Activity, int, int>>(Activities.Count);
+      var dependencies = new Dictionary<int, List<int>>(Activities.Count);
+      activities.Add( /*[Activities[0].Number] =*/ Tuple.Create(Activities[0], int.MinValue, 1));
+      dependencies[Activities[0].Number] = new List<int>();
+      for (var i = 1; i < Activities.Count - 1; i++) {
+        activities.Add( /*[Activities[i].Number] =*/ Tuple.Create(Activities[i], randomKey[i - 1], modeList[i - 1]));
+        dependencies[Activities[i].Number] = new List<int>();
+      }
+
+      activities.Add( /*[Activities[Activities.Count - 1].Number] =*/
+        Tuple.Create(Activities[Activities[Activities.Count - 1].Number], int.MaxValue, 1));
+      dependencies[Activities[Activities.Count - 1].Number] = new List<int>();
+
+      foreach (var activity in Activities) {
+        foreach (var successor in activity.Successors) {
+          dependencies[successor.Value].Add(activity.Number);
+        }
+      }
+
+      activities = activities.OrderBy(a => a.Item2).ToList();
+
+      var env = new Environment();
+      var procActivities = new Dictionary<int, Process>();
+
+      var resources = new Dictionary<int, Container>();
+      foreach (var resource in ResourceCapacities.Where(r => r.IsRenewable)) {
+        resources.Add(resource.Number, new Container(env, resource.Capacity, resource.Capacity));
+      }
+
+      var nonrenRes = new Dictionary<int, Container>();
+      foreach (var resource in ResourceCapacities.Where(r => !r.IsRenewable)) {
+        nonrenRes.Add(resource.Number, new Container(env, resource.Capacity, resource.Capacity));
+      }
+
+      foreach (var act in activities) {
+        procActivities[act.Item1.Number] = env.Process(Job(env, procActivities, act, resources, nonrenRes,
+          dependencies[act.Item1.Number]));
+      }
+
+      // fitness function by Hartmann (2001)
+      try {
+        env.Run();
+      } catch (InvalidOperationException) {
+        var T = Activities.Sum(a => a.Modes.Max(m =>
+                  m.ResourceDemands.Where(d => ResourceCapacities.Single(c => c.Number == d.Number).IsRenewable)
+                    .Sum(d => d.Demand)));
+        var ERR = activities.Sum(a => a.Item1.Modes[a.Item3 - 1].ResourceDemands
+            .Where(d => !ResourceCapacities.Single(c => c.Number == d.Number).IsRenewable).Sum(r => r.Demand));
+
+        return T + ERR;
+      }
+
+      return env.NowD;
+    }
+
+    private bool IsRenewable(int resourceNumber) => ResourceCapacities.Single(r => r.Number == resourceNumber).IsRenewable;
+
+    private IEnumerable<Event> Job(Environment env, Dictionary<int, Process> procActivities, Tuple<Activity, int, int> act,
+      Dictionary<int, Container> resources, Dictionary<int, Container> nonrenRes, IEnumerable<int> deps) {
+      var mode = act.Item1.Modes[act.Item3 - 1];
+      var timeout = mode.Duration;
+      var demands = mode.ResourceDemands.Where(r => r.Demand > 0);
+      var res = demands.Where(r => IsRenewable(r.Number)).Select(r => Tuple.Create(resources[r.Number], r.Demand, r.Number));
+      var nres = demands.Where(r => !IsRenewable(r.Number)).Select(r => Tuple.Create(nonrenRes[r.Number], r.Demand, r.Number));
+
+      yield return new AllOf(env, deps.Select(d => procActivities[d]));
+      //Console.WriteLine(act.Item1.Number + " B " + env.NowD);
+
+      foreach (var nr in nres) {
+        if (nr.Item2 > nonrenRes[nr.Item3].Level)
+          throw new InvalidOperationException();
+        yield return nonrenRes[nr.Item3].Get(nr.Item2);
+      }
+
+      foreach (var r in res) {
+        yield return r.Item1.Get(r.Item2);
+        yield return env.TimeoutD(timeout);
+        yield return r.Item1.Put(r.Item2);
+        //for (var t = 0; t < r.Item2; t++) {
+        //  using (var req = r.Item1.Request()) {
+        //    yield return req;
+        //    yield return env.TimeoutD(timeout);
+        //  }
+        //}
+        //Console.WriteLine(act.Item1.Number + " E " + env.NowD);
+      }
+    }
+  }
+}
+
Index: /branches/2981_MRCPSP/UnitTestProject/UnitTestProject.csproj
===================================================================
--- /branches/2981_MRCPSP/UnitTestProject/UnitTestProject.csproj	(revision 16598)
+++ /branches/2981_MRCPSP/UnitTestProject/UnitTestProject.csproj	(revision 16598)
@@ -0,0 +1,95 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
+  <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>{717869DF-EEE7-4CB7-AE7E-80769C32C180}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>UnitTestProject</RootNamespace>
+    <AssemblyName>UnitTestProject</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
+    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
+    <IsCodedUITest>False</IsCodedUITest>
+    <TestProjectType>UnitTest</TestProjectType>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3">
+      <HintPath>..\..\..\trunk\bin\HeuristicLab.Collections-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Common-3.3">
+      <HintPath>..\..\..\trunk\bin\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3">
+      <HintPath>..\..\..\trunk\bin\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3">
+      <HintPath>..\..\..\trunk\bin\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Encodings.IntegerVectorEncoding-3.3">
+      <HintPath>..\..\..\trunk\bin\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3">
+      <HintPath>..\..\..\trunk\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
+    </Reference>
+    <Reference Include="SimSharp-3.0.11">
+      <HintPath>..\..\..\trunk\bin\SimSharp-3.0.11.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="UnitTest.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\HeuristicLab.Problem.Scheduling.MRCPSP\3.3\HeuristicLab.Problem.Scheduling.MRCPSP-3.3.csproj">
+      <Project>{CCD920DC-6058-440B-A0A3-1527984AABD3}</Project>
+      <Name>HeuristicLab.Problem.Scheduling.MRCPSP-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
+    <Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
+  </Target>
+  <Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
+</Project>
Index: /branches/2981_MRCPSP/UnitTestProject/packages.config
===================================================================
--- /branches/2981_MRCPSP/UnitTestProject/packages.config	(revision 16598)
+++ /branches/2981_MRCPSP/UnitTestProject/packages.config	(revision 16598)
@@ -0,0 +1,5 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net461" />
+  <package id="MSTest.TestFramework" version="1.3.2" targetFramework="net461" />
+</packages>
