Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab 3.3.sln
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab 3.3.sln	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab 3.3.sln	(revision 16892)
@@ -462,4 +462,6 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Algorithms.MOCMAEvolutionStrategy-3.3", "HeuristicLab.Algorithms.MOCMAEvolutionStrategy\3.3\HeuristicLab.Algorithms.MOCMAEvolutionStrategy-3.3.csproj", "{0E2E224F-E9B2-41F3-B510-09183EEBA2AF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Algorithms.DataAnalysis.M5-3.4", "HeuristicLab.Algorithms.DataAnalysis.M5\3.4\HeuristicLab.Algorithms.DataAnalysis.M5-3.4.csproj", "{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.DynamicalSystemsModelling-3.3", "HeuristicLab.Problems.DynamicalSystemsModelling\3.3\HeuristicLab.Problems.DynamicalSystemsModelling-3.3.csproj", "{EDCC8202-4463-4122-B01F-21B664343DFB}"
@@ -2253,4 +2255,16 @@
 		{0E2E224F-E9B2-41F3-B510-09183EEBA2AF}.Release|x86.ActiveCfg = Release|x86
 		{0E2E224F-E9B2-41F3-B510-09183EEBA2AF}.Release|x86.Build.0 = Release|x86
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Debug|x64.Build.0 = Debug|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Debug|x86.Build.0 = Debug|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|x64.ActiveCfg = Release|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|x64.Build.0 = Release|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|x86.ActiveCfg = Release|Any CPU
+		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|x86.Build.0 = Release|Any CPU
 		{EDCC8202-4463-4122-B01F-21B664343DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{EDCC8202-4463-4122-B01F-21B664343DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithm.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithm.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsGeneticAlgorithm.cs	(revision 16892)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Collections;
@@ -32,5 +33,4 @@
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.PluginInfrastructure;
 using HeuristicLab.Random;
@@ -444,7 +444,7 @@
       base.OnProblemChanged();
       ParameterizeStochasticOperator(Problem.SolutionCreator);
-      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
       foreach (var @operator in Problem.Operators.OfType<IOperator>())
         ParameterizeStochasticOperator(@operator);
+      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
 
       ParameterizeIterationBasedOperators();
@@ -478,5 +478,4 @@
       base.Problem_SolutionCreatorChanged(sender, e);
       ParameterizeStochasticOperator(Problem.SolutionCreator);
-      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
 
       Problem.Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
@@ -487,9 +486,5 @@
     protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
       base.Problem_EvaluatorChanged(sender, e);
-
       ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
-
-      foreach (var @operator in Problem.Operators.OfType<IOperator>())
-        ParameterizeStochasticOperator(@operator);
 
       UpdateAnalyzers();
@@ -501,4 +496,6 @@
     protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
       base.Problem_OperatorsChanged(sender, e);
+      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
+      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
       ParameterizeIterationBasedOperators();
       UpdateCrossovers();
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelectionGeneticAlgorithm.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelectionGeneticAlgorithm.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelectionGeneticAlgorithm.cs	(revision 16892)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Collections;
@@ -32,5 +33,4 @@
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.PluginInfrastructure;
 using HeuristicLab.Random;
@@ -507,7 +507,7 @@
       base.OnProblemChanged();
       ParameterizeStochasticOperator(Problem.SolutionCreator);
-      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
       foreach (var @operator in Problem.Operators.OfType<IOperator>())
         ParameterizeStochasticOperator(@operator);
+      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
 
       ParameterizeIterationBasedOperators();
@@ -541,5 +541,4 @@
       base.Problem_SolutionCreatorChanged(sender, e);
       ParameterizeStochasticOperator(Problem.SolutionCreator);
-      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
 
       Problem.Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
@@ -550,6 +549,5 @@
     protected override void Problem_EvaluatorChanged(object sender, EventArgs e) {
       base.Problem_EvaluatorChanged(sender, e);
-      foreach (var @operator in Problem.Operators.OfType<IOperator>())
-        ParameterizeStochasticOperator(@operator);
+      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
 
       UpdateAnalyzers();
@@ -561,4 +559,6 @@
     protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
       base.Problem_OperatorsChanged(sender, e);
+      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
+      ParameterizeStochasticOperatorForLayer(Problem.Evaluator);
       ParameterizeIterationBasedOperators();
       UpdateCrossovers();
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelectionGeneticAlgorithmMainOperator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelectionGeneticAlgorithmMainOperator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.ALPS/3.3/AlpsOffspringSelectionGeneticAlgorithmMainOperator.cs	(revision 16892)
@@ -20,4 +20,5 @@
 #endregion
 
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -26,5 +27,4 @@
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.Selection;
 
@@ -266,9 +266,9 @@
 
       variableCreator1.Name = "MutatedOffspring = true";
-      variableCreator1.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(true), false));
+      variableCreator1.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(true)) { GetsCollected = false });
       variableCreator1.Successor = null;
 
       variableCreator2.Name = "MutatedOffspring = false";
-      variableCreator2.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(false), false));
+      variableCreator2.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(false)) { GetsCollected = false });
       variableCreator2.Successor = null;
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/HeuristicLab.Algorithms.DataAnalysis.M5-3.4.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/HeuristicLab.Algorithms.DataAnalysis.M5-3.4.csproj	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/HeuristicLab.Algorithms.DataAnalysis.M5-3.4.csproj	(revision 16892)
@@ -0,0 +1,213 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Algorithms.DataAnalysis.M5</RootNamespace>
+    <AssemblyName>HeuristicLab.Algorithms.DataAnalysis.M5-3.4</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\bin\ALGLIB-3.7.0.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data.Linq" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Interfaces\ILeafModel.cs" />
+    <Compile Include="Interfaces\IM5Model.cs" />
+    <Compile Include="Interfaces\IPruning.cs" />
+    <Compile Include="Interfaces\ISplitter.cs" />
+    <Compile Include="LeafModels\ComponentReducedLinearModel.cs" />
+    <Compile Include="LeafModels\DampenedModel.cs" />
+    <Compile Include="LeafModels\PreconstructedLinearModel.cs" />
+    <Compile Include="LeafTypes\ComplexLeaf.cs" />
+    <Compile Include="LeafTypes\ComponentReductionLinearLeaf.cs" />
+    <Compile Include="LeafTypes\ConstantLeaf.cs" />
+    <Compile Include="LeafTypes\GaussianProcessLeaf.cs" />
+    <Compile Include="LeafTypes\LeafBase.cs" />
+    <Compile Include="LeafTypes\LinearLeaf.cs" />
+    <Compile Include="LeafTypes\M5Leaf.cs" />
+    <Compile Include="LeafTypes\M5regLeaf.cs" />
+    <Compile Include="M5Regression.cs" />
+    <Compile Include="M5Utilities\PrincipleComponentTransformation.cs" />
+    <Compile Include="M5Utilities\RegressionTreeAnalyzer.cs" />
+    <Compile Include="M5Utilities\RegressionTreeParameters.cs" />
+    <Compile Include="M5Utilities\RegressionTreeUtilities.cs" />
+    <Compile Include="MetaModels\RegressionNodeModel.cs" />
+    <Compile Include="MetaModels\RegressionNodeTreeModel.cs" />
+    <Compile Include="MetaModels\RegressionRuleModel.cs" />
+    <Compile Include="MetaModels\RegressionRuleSetModel.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Pruning\ComplexityPruning.cs" />
+    <Compile Include="Pruning\NoPruning.cs" />
+    <Compile Include="Splitting\CorrelationImpurityCalculator.cs" />
+    <Compile Include="Splitting\CorrelationSplitter.cs" />
+    <Compile Include="Splitting\M5Splitter.cs" />
+    <Compile Include="Splitting\NeumaierSum.cs" />
+    <Compile Include="Splitting\OrderImpurityCalculator.cs" />
+    <Compile Include="Splitting\SplitterBase.cs" />
+    <Compile Include="Splitting\UnivariateOnlineLR.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Algorithms.DataAnalysis.Glmnet\3.4\HeuristicLab.Algorithms.DataAnalysis.Glmnet-3.4.csproj">
+      <Project>{4c7f6d8a-b279-4898-acd6-7be39111def9}</Project>
+      <Name>HeuristicLab.Algorithms.DataAnalysis.Glmnet-3.4</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Algorithms.DataAnalysis\3.4\HeuristicLab.Algorithms.DataAnalysis-3.4.csproj">
+      <Project>{2e782078-fa81-4b70-b56f-74ce38dac6c8}</Project>
+      <Name>HeuristicLab.Algorithms.DataAnalysis-3.4</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425b4-4348-49ed-a457-b7d2c26ddbf9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958b43bc-cc5c-4fa2-8628-2b3b01d890b6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{a9ad58b9-3ef9-4cc1-97e5-8d909039ff5c}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{c36bd924-a541-4a00-afa8-41701378ddc5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{bbab9df5-5ef3-4ba8-ade9-b36e82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.PermutationEncoding\3.3\HeuristicLab.Encodings.PermutationEncoding-3.3.csproj">
+      <Project>{dbecb8b0-b166-4133-baf1-ed67c3fd7fca}</Project>
+      <Name>HeuristicLab.Encodings.PermutationEncoding-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding\3.4\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj">
+      <Project>{06D4A186-9319-48A0-BADE-A2058D462EEA}</Project>
+      <Name>HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14ab8d24-25bc-400c-a846-4627aa945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
+      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
+      <Name>HeuristicLab.Parameters-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis\3.4\HeuristicLab.Problems.DataAnalysis-3.4.csproj">
+      <Project>{df87c13e-a889-46ff-8153-66dcaa8c5674}</Project>
+      <Name>HeuristicLab.Problems.DataAnalysis-3.4</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances\3.3\HeuristicLab.Problems.Instances-3.3.csproj">
+      <Project>{3540e29e-4793-49e7-8ee2-fea7f61c3994}</Project>
+      <Name>HeuristicLab.Problems.Instances-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{f4539fb6-4708-40c9-be64-0a1390aea197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\bin\HEAL.Attic.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/ILeafModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/ILeafModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/ILeafModel.cs	(revision 16892)
@@ -0,0 +1,38 @@
+﻿#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.Collections.Generic;
+using System.Threading;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("2A4CB43C-51EB-47AF-AEDD-9B84B27D318B")]
+  public interface ILeafModel : IParameterizedNamedItem {
+    bool ProvidesConfidence { get; }
+    int MinLeafSize(IRegressionProblemData pd);
+
+    void Initialize(IScope states);
+    void Build(RegressionNodeTreeModel tree, IReadOnlyList<int> trainingRows, IScope stateScope, CancellationToken cancellationToken);
+    IRegressionModel BuildModel(IReadOnlyList<int> rows, RegressionTreeParameters parameters, CancellationToken cancellation, out int numParams);
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/IM5Model.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/IM5Model.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/IM5Model.cs	(revision 16892)
@@ -0,0 +1,35 @@
+﻿#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.Collections.Generic;
+using System.Threading;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("A5399E6A-6A4D-4616-A1CD-CE12FE670F12")]
+  public interface IM5Model : IRegressionModel {
+    void Build(IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope stateScope, ResultCollection results, CancellationToken cancellationToken);
+    void Update(IReadOnlyList<int> rows, IScope stateScope, CancellationToken cancellationToken);
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/IPruning.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/IPruning.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/IPruning.cs	(revision 16892)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+using System.Collections.Generic;
+using System.Threading;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("5CAADC16-DCF2-4562-A4DF-C3D5BA1E02A5")]
+  public interface IPruning : IParameterizedNamedItem {
+    int MinLeafSize(IRegressionProblemData pd, ILeafModel leafModel);
+
+    void Initialize(IScope states);
+    void Prune(RegressionNodeTreeModel treeModel, IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope scope, CancellationToken cancellationToken);
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/ISplitter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/ISplitter.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Interfaces/ISplitter.cs	(revision 16892)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+using System.Collections.Generic;
+using System.Threading;
+using HeuristicLab.Core;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("A6FB3D68-B298-4C89-9FD9-2D1415D131F5")]
+  public interface ISplitter : IParameterizedNamedItem {
+    void Initialize(IScope states);
+    void Split(RegressionNodeTreeModel tree, IReadOnlyList<int> trainingRows, IScope stateScope, CancellationToken cancellationToken);
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/ComponentReducedLinearModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/ComponentReducedLinearModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/ComponentReducedLinearModel.cs	(revision 16892)
@@ -0,0 +1,69 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("4E5B8317-648D-4A5A-A3F7-A1A5BEB9AA69")]
+  public sealed class ComponentReducedLinearModel : RegressionModel {
+    [Storable]
+    private IRegressionModel Model;
+    [Storable]
+    private PrincipleComponentTransformation Pca;
+
+    [StorableConstructor]
+    private ComponentReducedLinearModel(StorableConstructorFlag _) : base(_) { }
+    private ComponentReducedLinearModel(ComponentReducedLinearModel original, Cloner cloner) : base(original, cloner) {
+      Model = cloner.Clone(original.Model);
+      Pca = cloner.Clone(original.Pca);
+    }
+
+    public ComponentReducedLinearModel(string targetVariable, IRegressionModel model, PrincipleComponentTransformation pca) : base(targetVariable) {
+      Model = model;
+      Pca = pca;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ComponentReducedLinearModel(this, cloner);
+    }
+
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return Model.VariablesUsedForPrediction; }
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      var data = ReduceDataset(dataset, rows.ToArray());
+      return Model.GetEstimatedValues(Pca.TransformDataset(data), Enumerable.Range(0, data.Rows));
+    }
+
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+
+    private IDataset ReduceDataset(IDataset data, IReadOnlyList<int> rows) {
+      return new Dataset(data.DoubleVariables, data.DoubleVariables.Select(v => data.GetDoubleValues(v, rows).ToList()));
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/DampenedModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/DampenedModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/DampenedModel.cs	(revision 16892)
@@ -0,0 +1,124 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  //mulitdimensional extension of http://www2.stat.duke.edu/~tjl13/s101/slides/unit6lec3H.pdf
+  [StorableType("42E9766F-207F-47B1-890C-D5DFCF469838")]
+  public class DampenedModel : RegressionModel {
+    [Storable]
+    protected IRegressionModel Model;
+    [Storable]
+    private double Min;
+    [Storable]
+    private double Max;
+    [Storable]
+    private double Dampening;
+
+    [StorableConstructor]
+    protected DampenedModel(StorableConstructorFlag _) : base(_) { }
+    protected DampenedModel(DampenedModel original, Cloner cloner) : base(original, cloner) {
+      Model = cloner.Clone(original.Model);
+      Min = original.Min;
+      Max = original.Max;
+      Dampening = original.Dampening;
+    }
+    protected DampenedModel(IRegressionModel model, IRegressionProblemData pd, double dampening) : base(model.TargetVariable) {
+      Model = model;
+      Min = pd.TargetVariableTrainingValues.Min();
+      Max = pd.TargetVariableTrainingValues.Max();
+      Dampening = dampening;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DampenedModel(this, cloner);
+    }
+
+    public static IConfidenceRegressionModel DampenModel(IConfidenceRegressionModel model, IRegressionProblemData pd, double dampening) {
+      return new ConfidenceDampenedModel(model, pd, dampening);
+    }
+    public static IRegressionModel DampenModel(IRegressionModel model, IRegressionProblemData pd, double dampening) {
+      var cmodel = model as IConfidenceRegressionModel;
+      return cmodel != null ? new ConfidenceDampenedModel(cmodel, pd, dampening) : new DampenedModel(model, pd, dampening);
+    }
+
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return Model.VariablesUsedForPrediction; }
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      var slow = Sigmoid(-Dampening);
+      var shigh = Sigmoid(Dampening);
+      foreach (var x in Model.GetEstimatedValues(dataset, rows)) {
+        var y = Rescale(x, Min, Max, -Dampening, Dampening);
+        y = Sigmoid(y);
+        y = Rescale(y, slow, shigh, Min, Max);
+        yield return y;
+      }
+    }
+
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+
+    private static double Rescale(double x, double oMin, double oMax, double nMin, double nMax) {
+      var d = oMax - oMin;
+      var nd = nMax - nMin;
+      if (d.IsAlmost(0)) {
+        d = 1;
+        nMin += nd / 2;
+        nd = 0;
+      }
+      return ((x - oMin) / d) * nd + nMin;
+    }
+
+    private static double Sigmoid(double x) {
+      return 1 / (1 + Math.Exp(-x));
+    }
+
+
+    [StorableType("CCC93BEC-8796-4D8E-AC58-DD175073A79B")]
+    private sealed class ConfidenceDampenedModel : DampenedModel, IConfidenceRegressionModel {
+      #region HLConstructors
+      [StorableConstructor]
+      private ConfidenceDampenedModel(StorableConstructorFlag _) : base(_) { }
+      private ConfidenceDampenedModel(ConfidenceDampenedModel original, Cloner cloner) : base(original, cloner) { }
+      public ConfidenceDampenedModel(IConfidenceRegressionModel model, IRegressionProblemData pd, double dampening) : base(model, pd, dampening) { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new ConfidenceDampenedModel(this, cloner);
+      }
+      #endregion
+
+      public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+        return ((IConfidenceRegressionModel)Model).GetEstimatedVariances(dataset, rows);
+      }
+
+      public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+        return new ConfidenceRegressionSolution(this, problemData);
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/PreconstructedLinearModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/PreconstructedLinearModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafModels/PreconstructedLinearModel.cs	(revision 16892)
@@ -0,0 +1,153 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  //mulitdimensional extension of http://www2.stat.duke.edu/~tjl13/s101/slides/unit6lec3H.pdf
+  [StorableType("15F2295C-28C1-48C3-8DCB-9470823C6734")]
+  internal sealed class PreconstructedLinearModel : RegressionModel {
+    [Storable]
+    public Dictionary<string, double> Coefficients { get; private set; }
+    [Storable]
+    public double Intercept { get; private set; }
+
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return Coefficients.Keys; }
+    }
+
+    #region HLConstructors
+    [StorableConstructor]
+    private PreconstructedLinearModel(StorableConstructorFlag _) : base(_) { }
+    private PreconstructedLinearModel(PreconstructedLinearModel original, Cloner cloner) : base(original, cloner) {
+      if (original.Coefficients != null) Coefficients = original.Coefficients.ToDictionary(x => x.Key, x => x.Value);
+      Intercept = original.Intercept;
+    }
+    public PreconstructedLinearModel(Dictionary<string, double> coefficients, double intercept, string targetvariable) : base(targetvariable) {
+      Coefficients = new Dictionary<string, double>(coefficients);
+      Intercept = intercept;
+    }
+    public PreconstructedLinearModel(double intercept, string targetvariable) : base(targetvariable) {
+      Coefficients = new Dictionary<string, double>();
+      Intercept = intercept;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PreconstructedLinearModel(this, cloner);
+    }
+    #endregion
+
+    public static PreconstructedLinearModel CreateLinearModel(IRegressionProblemData pd, out double rmse) {
+      return AlternativeCalculation(pd, out rmse);
+    }
+
+    private static PreconstructedLinearModel ClassicCalculation(IRegressionProblemData pd) {
+      var inputMatrix = pd.Dataset.ToArray(pd.AllowedInputVariables.Concat(new[] {
+        pd.TargetVariable
+      }), pd.AllIndices);
+
+      var nFeatures = inputMatrix.GetLength(1) - 1;
+      double[] coefficients;
+
+      alglib.linearmodel lm;
+      alglib.lrreport ar;
+      int retVal;
+      alglib.lrbuild(inputMatrix, inputMatrix.GetLength(0), nFeatures, out retVal, out lm, out ar);
+      if (retVal != 1) throw new ArgumentException("Error in calculation of linear regression solution");
+
+      alglib.lrunpack(lm, out coefficients, out nFeatures);
+      var coeffs = pd.AllowedInputVariables.Zip(coefficients, (s, d) => new {s, d}).ToDictionary(x => x.s, x => x.d);
+      var res = new PreconstructedLinearModel(coeffs, coefficients[nFeatures], pd.TargetVariable);
+      return res;
+    }
+
+    private static PreconstructedLinearModel AlternativeCalculation(IRegressionProblemData pd, out double rmse) {
+      var variables = pd.AllowedInputVariables.ToList();
+      var n = variables.Count;
+      var m = pd.TrainingIndices.Count();
+
+      //Set up X^T
+      var inTr = new double[n + 1, m];
+      for (var i = 0; i < n; i++) {
+        var vdata = pd.Dataset.GetDoubleValues(variables[i], pd.TrainingIndices).ToArray();
+        for (var j = 0; j < m; j++) inTr[i, j] = vdata[j];
+      }
+      for (var i = 0; i < m; i++) inTr[n, i] = 1;
+
+      //Set up y
+      var y = new double[m, 1];
+      var ydata = pd.TargetVariableTrainingValues.ToArray();
+      for (var i = 0; i < m; i++) y[i, 0] = ydata[i];
+
+      //Perform linear regression
+      var aTy = new double[n + 1, 1];
+      var aTa = new double[n + 1, n + 1];
+      var aTyVector = new double[n + 1];
+      int info;
+      alglib.densesolverreport report;
+      double[] coefficients;
+
+      //Perform linear regression
+      alglib.rmatrixgemm(n + 1, 1, m, 1, inTr, 0, 0, 0, y, 0, 0, 0, 0, ref aTy, 0, 0); //aTy = inTr * y;
+      alglib.rmatrixgemm(n + 1, n + 1, m, 1, inTr, 0, 0, 0, inTr, 0, 0, 1, 0, ref aTa, 0, 0); //aTa = inTr * t(inTr) +aTa //
+      alglib.spdmatrixcholesky(ref aTa, n + 1, true);
+      for (var i = 0; i < n + 1; i++) aTyVector[i] = aTy[i, 0];
+      alglib.spdmatrixcholeskysolve(aTa, n + 1, true, aTyVector, out info, out report, out coefficients);
+
+      //if Cholesky calculation fails fall back to classic linear regresseion 
+      if (info != 1) {
+        alglib.linearmodel lm;
+        alglib.lrreport ar;
+        int retVal;
+        var inputMatrix = pd.Dataset.ToArray(pd.AllowedInputVariables.Concat(new[] {
+          pd.TargetVariable
+        }), pd.AllIndices);
+        alglib.lrbuild(inputMatrix, inputMatrix.GetLength(0), n, out retVal, out lm, out ar);
+        if (retVal != 1) throw new ArgumentException("Error in calculation of linear regression solution");
+        alglib.lrunpack(lm, out coefficients, out n);
+      }
+
+      var coeffs = Enumerable.Range(0, n).ToDictionary(i => variables[i], i => coefficients[i]);
+      var model = new PreconstructedLinearModel(coeffs, coefficients[n], pd.TargetVariable);
+      rmse = pd.TrainingIndices.Select(i => pd.Dataset.GetDoubleValue(pd.TargetVariable, i) - model.GetEstimatedValue(pd.Dataset, i)).Sum(r => r * r) / m;
+      rmse = Math.Sqrt(rmse);
+      return model;
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      return rows.Select(row => GetEstimatedValue(dataset, row));
+    }
+
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+
+    #region helpers
+    private double GetEstimatedValue(IDataset dataset, int row) {
+      return Intercept + (Coefficients.Count == 0 ? 0 : Coefficients.Sum(s => s.Value * dataset.GetDoubleValue(s.Key, row)));
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ComplexLeaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ComplexLeaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ComplexLeaf.cs	(revision 16892)
@@ -0,0 +1,75 @@
+﻿#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 System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("F34A0ED9-2CF6-4DEE-850D-08790663B66D")]
+  [Item("ComplexLeaf", "A leaf type that uses an arbitrary RegressionAlgorithm to create leaf models")]
+  public sealed class ComplexLeaf : LeafBase {
+    public const string RegressionParameterName = "Regression";
+    public IValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>> RegressionParameter {
+      get { return (IValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>>)Parameters[RegressionParameterName]; }
+    }
+    public IDataAnalysisAlgorithm<IRegressionProblem> Regression {
+      get { return RegressionParameter.Value; }
+      set { RegressionParameter.Value = value; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private ComplexLeaf(StorableConstructorFlag _) : base(_) { }
+    private ComplexLeaf(ComplexLeaf original, Cloner cloner) : base(original, cloner) { }
+    public ComplexLeaf() {
+      var regression = new KernelRidgeRegression();
+      Parameters.Add(new ValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>>(RegressionParameterName, "The algorithm creating RegressionModels", regression));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ComplexLeaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return false; }
+    }
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int noParameters) {
+      if (pd.Dataset.Rows < MinLeafSize(pd)) throw new ArgumentException("The number of training instances is too small to create a linear model");
+      noParameters = pd.Dataset.Rows + 1;
+      Regression.Problem = new RegressionProblem { ProblemData = pd };
+      var res = RegressionTreeUtilities.RunSubAlgorithm(Regression, random.Next(), cancellationToken);
+      var t = res.Select(x => x.Value).OfType<IRegressionSolution>().FirstOrDefault();
+      if (t == null) throw new ArgumentException("No RegressionSolution was provided by the algorithm");
+      return t.Model;
+    }
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return 3;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ComponentReductionLinearLeaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ComponentReductionLinearLeaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ComponentReductionLinearLeaf.cs	(revision 16892)
@@ -0,0 +1,90 @@
+﻿#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("5730B54C-7A8B-4CA7-8F37-7FF3F9848CD2")]
+  [Item("ComponentReductionLinearLeaf", "A leaf type that uses principle component analysis to create smaller linear models as leaf models")]
+  public class ComponentReductionLinearLeaf : LeafBase {
+    public const string NumberOfComponentsParameterName = "NoComponents";
+    public IFixedValueParameter<IntValue> NumberOfCompontentsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[NumberOfComponentsParameterName]; }
+    }
+    public int NumberOfComponents {
+      get { return NumberOfCompontentsParameter.Value.Value; }
+      set { NumberOfCompontentsParameter.Value.Value = value; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected ComponentReductionLinearLeaf(StorableConstructorFlag _) : base(_) { }
+    protected ComponentReductionLinearLeaf(ComponentReductionLinearLeaf original, Cloner cloner) : base(original, cloner) { }
+    public ComponentReductionLinearLeaf() {
+      Parameters.Add(new FixedValueParameter<IntValue>(NumberOfComponentsParameterName, "The maximum number of principle components used (default=10)", new IntValue(10)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ComponentReductionLinearLeaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return false; }
+    }
+
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random,
+      CancellationToken cancellationToken, out int numberOfParameters) {
+      var pca = PrincipleComponentTransformation.CreateProjection(pd.Dataset, pd.TrainingIndices, pd.AllowedInputVariables, normalize: true);
+      var pcdata = pca.TransformProblemData(pd);
+      ComponentReducedLinearModel bestModel = null;
+      var bestCvrmse = double.MaxValue;
+      numberOfParameters = 1;
+      for (var i = 1; i <= Math.Min(NumberOfComponents, pd.AllowedInputVariables.Count()); i++) {
+        var pd2 = (IRegressionProblemData)pcdata.Clone();
+        var inputs = new HashSet<string>(pca.ComponentNames.Take(i));
+        foreach (var v in pd2.InputVariables.CheckedItems.ToArray())
+          pd2.InputVariables.SetItemCheckedState(v.Value, inputs.Contains(v.Value.Value));
+        double rmse;
+        var model = PreconstructedLinearModel.CreateLinearModel(pd2, out rmse);
+        if (rmse > bestCvrmse) continue;
+        bestModel = new ComponentReducedLinearModel(pd2.TargetVariable, model, pca);
+        numberOfParameters = i + 1;
+        bestCvrmse = rmse;
+      }
+      return bestModel;
+    }
+
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return NumberOfComponents + 2;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ConstantLeaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ConstantLeaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/ConstantLeaf.cs	(revision 16892)
@@ -0,0 +1,59 @@
+﻿#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 System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("F3E94907-C5FF-4658-A870-8013C61DD2E1")]
+  [Item("ConstantLeaf", "A leaf type that uses constant models as leaf models")]
+  public class ConstantLeaf : LeafBase {
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected ConstantLeaf(StorableConstructorFlag _) : base(_) { }
+    protected ConstantLeaf(ConstantLeaf original, Cloner cloner) : base(original, cloner) { }
+    public ConstantLeaf() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ConstantLeaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return false; }
+    }
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int numberOfParameters) {
+      if (pd.Dataset.Rows < MinLeafSize(pd)) throw new ArgumentException("The number of training instances is too small to create a linear model");
+      numberOfParameters = 1;
+      return new PreconstructedLinearModel(pd.Dataset.GetDoubleValues(pd.TargetVariable).Average(), pd.TargetVariable);
+    }
+
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return 0;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/GaussianProcessLeaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/GaussianProcessLeaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/GaussianProcessLeaf.cs	(revision 16892)
@@ -0,0 +1,111 @@
+﻿#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 System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("852B9F7D-9C2B-4574-BB71-EE70106EA809")]
+  [Item("GaussianProcessLeaf", "A leaf type that uses Gaussian process models as leaf models.")]
+  public class GaussianProcessLeaf : LeafBase {
+    #region ParameterNames
+    public const string TriesParameterName = "Tries";
+    public const string RegressionParameterName = "Regression";
+    #endregion
+
+    #region ParameterProperties
+    public IFixedValueParameter<IntValue> TriesParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[TriesParameterName]; }
+    }
+    public IValueParameter<GaussianProcessRegression> RegressionParameter {
+      get { return (IValueParameter<GaussianProcessRegression>)Parameters[RegressionParameterName]; }
+    }
+    #endregion
+
+    #region Properties
+    public int Tries {
+      get { return TriesParameter.Value.Value; }
+      set { TriesParameter.Value.Value = value; }
+    }
+    public GaussianProcessRegression Regression {
+      get { return RegressionParameter.Value; }
+      set { RegressionParameter.Value = value; }
+    }
+    #endregion
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected GaussianProcessLeaf(StorableConstructorFlag _) : base(_) { }
+    protected GaussianProcessLeaf(GaussianProcessLeaf original, Cloner cloner) : base(original, cloner) { }
+    public GaussianProcessLeaf() {
+      var gp = new GaussianProcessRegression();
+      gp.CovarianceFunctionParameter.Value = new CovarianceRationalQuadraticIso();
+      gp.MeanFunctionParameter.Value = new MeanLinear();
+
+      Parameters.Add(new FixedValueParameter<IntValue>(TriesParameterName, "Number of restarts (default = 10)", new IntValue(10)));
+      Parameters.Add(new ValueParameter<GaussianProcessRegression>(RegressionParameterName, "The algorithm creating Gaussian process models", gp));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GaussianProcessLeaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return true; }
+    }
+
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int numberOfParameters) {
+      if (pd.Dataset.Rows < MinLeafSize(pd)) throw new ArgumentException("The number of training instances is too small to create a Gaussian process model");
+      Regression.Problem = new RegressionProblem { ProblemData = pd };
+      var cvscore = double.MaxValue;
+      GaussianProcessRegressionSolution sol = null;
+
+      for (var i = 0; i < Tries; i++) {
+        var res = RegressionTreeUtilities.RunSubAlgorithm(Regression, random.Next(), cancellationToken);
+        var t = res.Select(x => x.Value).OfType<GaussianProcessRegressionSolution>().FirstOrDefault();
+        var score = ((DoubleValue)res["Negative log pseudo-likelihood (LOO-CV)"].Value).Value;
+        if (score >= cvscore || t == null || double.IsNaN(t.TrainingRSquared)) continue;
+        cvscore = score;
+        sol = t;
+      }
+      Regression.Runs.Clear();
+      if (sol == null) throw new ArgumentException("Could not create Gaussian process model");
+
+      numberOfParameters = pd.Dataset.Rows + 1
+                           + Regression.CovarianceFunction.GetNumberOfParameters(pd.AllowedInputVariables.Count())
+                           + Regression.MeanFunction.GetNumberOfParameters(pd.AllowedInputVariables.Count());
+      return sol.Model;
+    }
+
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return 3;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/LeafBase.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/LeafBase.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/LeafBase.cs	(revision 16892)
@@ -0,0 +1,167 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("F3A9CCD4-975F-4F55-BE24-3A3E932591F6")]
+  public abstract class LeafBase : ParameterizedNamedItem, ILeafModel {
+    public const string LeafBuildingStateVariableName = "LeafBuildingState";
+    public const string UseDampeningParameterName = "UseDampening";
+    public const string DampeningParameterName = "DampeningStrength";
+
+    public IFixedValueParameter<DoubleValue> DampeningParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[DampeningParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> UseDampeningParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[UseDampeningParameterName]; }
+    }
+
+    public bool UseDampening {
+      get { return UseDampeningParameter.Value.Value; }
+      set { UseDampeningParameter.Value.Value = value; }
+    }
+    public double Dampening {
+      get { return DampeningParameter.Value.Value; }
+      set { DampeningParameter.Value.Value = value; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected LeafBase(StorableConstructorFlag _) : base(_) { }
+    protected LeafBase(LeafBase original, Cloner cloner) : base(original, cloner) { }
+    protected LeafBase() {
+      Parameters.Add(new FixedValueParameter<BoolValue>(UseDampeningParameterName, "Whether logistic dampening should be used to prevent extreme extrapolation (default=false)", new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(DampeningParameterName, "Determines the strength of logistic dampening. Must be > 0.0. Larger numbers lead to more conservative predictions. (default=1.5)", new DoubleValue(1.5)));
+    }
+    #endregion
+
+    #region IModelType
+    public abstract bool ProvidesConfidence { get; }
+    public abstract int MinLeafSize(IRegressionProblemData pd);
+
+    public void Initialize(IScope states) {
+      states.Variables.Add(new Variable(LeafBuildingStateVariableName, new LeafBuildingState()));
+    }
+
+    public void Build(RegressionNodeTreeModel tree, IReadOnlyList<int> trainingRows, IScope stateScope, CancellationToken cancellationToken) {
+      var parameters = (RegressionTreeParameters)stateScope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      var state = (LeafBuildingState)stateScope.Variables[LeafBuildingStateVariableName].Value;
+
+      if (state.Code == 0) {
+        state.FillLeafs(tree, trainingRows, parameters.Data);
+        state.Code = 1;
+      }
+      while (state.nodeQueue.Count != 0) {
+        var n = state.nodeQueue.Peek();
+        var t = state.trainingRowsQueue.Peek();
+        int numP;
+        n.SetLeafModel(BuildModel(t, parameters, cancellationToken, out numP));
+        state.nodeQueue.Dequeue();
+        state.trainingRowsQueue.Dequeue();
+      }
+    }
+
+    public IRegressionModel BuildModel(IReadOnlyList<int> rows, RegressionTreeParameters parameters, CancellationToken cancellation, out int numberOfParameters) {
+      var reducedData = RegressionTreeUtilities.ReduceDataset(parameters.Data, rows, parameters.AllowedInputVariables.ToArray(), parameters.TargetVariable);
+      var pd = new RegressionProblemData(reducedData, parameters.AllowedInputVariables.ToArray(), parameters.TargetVariable);
+      pd.TrainingPartition.Start = 0;
+      pd.TrainingPartition.End = pd.TestPartition.Start = pd.TestPartition.End = reducedData.Rows;
+
+      int numP;
+      var model = Build(pd, parameters.Random, cancellation, out numP);
+      if (UseDampening && Dampening > 0.0) {
+        model = DampenedModel.DampenModel(model, pd, Dampening);
+      }
+
+      numberOfParameters = numP;
+      cancellation.ThrowIfCancellationRequested();
+      return model;
+    }
+
+    public abstract IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int numberOfParameters);
+    #endregion
+
+    [StorableType("495243C0-6C15-4328-B30D-FFBFA0F54DCB")]
+    public class LeafBuildingState : Item {
+      [Storable]
+      public Queue<RegressionNodeModel> nodeQueue = new Queue<RegressionNodeModel>();
+      [Storable]
+      public Queue<IReadOnlyList<int>> trainingRowsQueue = new Queue<IReadOnlyList<int>>();
+
+      //State.Code values denote the current action (for pausing)
+      //0...nothing has been done;
+      //1...building models;
+      [Storable]
+      public int Code = 0;
+
+      #region HLConstructors & Cloning
+      [StorableConstructor]
+      protected LeafBuildingState(StorableConstructorFlag _) : base(_) { }
+      protected LeafBuildingState(LeafBuildingState original, Cloner cloner) : base(original, cloner) {
+        nodeQueue = new Queue<RegressionNodeModel>(original.nodeQueue.Select(cloner.Clone));
+        trainingRowsQueue = new Queue<IReadOnlyList<int>>(original.trainingRowsQueue.Select(x => (IReadOnlyList<int>)x.ToArray()));
+        Code = original.Code;
+      }
+      public LeafBuildingState() { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new LeafBuildingState(this, cloner);
+      }
+      #endregion
+
+      public void FillLeafs(RegressionNodeTreeModel tree, IReadOnlyList<int> trainingRows, IDataset data) {
+        var helperQueue = new Queue<RegressionNodeModel>();
+        var trainingHelperQueue = new Queue<IReadOnlyList<int>>();
+        nodeQueue.Clear();
+        trainingRowsQueue.Clear();
+
+        helperQueue.Enqueue(tree.Root);
+        trainingHelperQueue.Enqueue(trainingRows);
+
+        while (helperQueue.Count != 0) {
+          var n = helperQueue.Dequeue();
+          var t = trainingHelperQueue.Dequeue();
+          if (n.IsLeaf) {
+            nodeQueue.Enqueue(n);
+            trainingRowsQueue.Enqueue(t);
+            continue;
+          }
+
+          IReadOnlyList<int> leftTraining, rightTraining;
+          RegressionTreeUtilities.SplitRows(t, data, n.SplitAttribute, n.SplitValue, out leftTraining, out rightTraining);
+
+          helperQueue.Enqueue(n.Left);
+          helperQueue.Enqueue(n.Right);
+          trainingHelperQueue.Enqueue(leftTraining);
+          trainingHelperQueue.Enqueue(rightTraining);
+        }
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/LinearLeaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/LinearLeaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/LinearLeaf.cs	(revision 16892)
@@ -0,0 +1,61 @@
+﻿#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 System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("347CA25D-FB37-4C4F-9B61-9D79288B2B28")]
+  [Item("LinearLeaf", "A leaf type that uses linear models as leaf models. This is the standard for M5' regression")]
+  public class LinearLeaf : LeafBase {
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected LinearLeaf(StorableConstructorFlag _) : base(_) { }
+    protected LinearLeaf(LinearLeaf original, Cloner cloner) : base(original, cloner) { }
+    public LinearLeaf() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LinearLeaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return true; }
+    }
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int numberOfParameters) {
+      if (pd.Dataset.Rows < MinLeafSize(pd)) throw new ArgumentException("The number of training instances is too small to create a linear model");
+      double rmse, cvRmse;
+      numberOfParameters = pd.AllowedInputVariables.Count() + 1;
+      var res = LinearRegression.CreateSolution(pd, out rmse, out cvRmse);
+      return res.Model;
+    }
+
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return pd.AllowedInputVariables.Count() == 1 ? 2 : pd.AllowedInputVariables.Count() + 2;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/M5Leaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/M5Leaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/M5Leaf.cs	(revision 16892)
@@ -0,0 +1,198 @@
+﻿#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("58517042-5318-4087-B098-AC75F0208BA0")]
+  [Item("M5Leaf", "A leaf type that uses regularized linear models with feature selection as leaf models.")]
+  public sealed class M5Leaf : LeafBase {
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private M5Leaf(StorableConstructorFlag _) : base(_) { }
+    private M5Leaf(M5Leaf original, Cloner cloner) : base(original, cloner) { }
+    public M5Leaf() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new M5Leaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return false; }
+    }
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int numberOfParameters) {
+      if (pd.Dataset.Rows == 0) throw new ArgumentException("The number of training instances is too small to create an M5 leaf model");
+
+      if (pd.Dataset.Rows == 1)
+        return new ConstantLeaf().Build(pd, random, cancellationToken, out numberOfParameters);
+
+      var means = pd.AllowedInputVariables.ToDictionary(n => n, n => pd.Dataset.GetDoubleValues(n, pd.TrainingIndices).Average());
+      var variances = pd.AllowedInputVariables.ToDictionary(n => n, n => pd.Dataset.GetDoubleValues(n, pd.TrainingIndices).Variance());
+      var used = pd.AllowedInputVariables.Where(v => !variances[v].IsAlmost(0.0)).ToList();
+
+      var targetMean = pd.TargetVariableTrainingValues.Average();
+      var targetVariance = pd.TargetVariableTrainingValues.Variance();
+
+      var model = FindBestModel(variances, means, targetMean, targetVariance, pd, used);
+      numberOfParameters = 1 + model.Coefficients.Count;
+      return model;
+    }
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return 1;
+    }
+    #endregion
+
+    private static PreconstructedLinearModel FindBestModel(Dictionary<string, double> variances, Dictionary<string, double> means, double yMean, double yVariance, IRegressionProblemData pd, IList<string> variables) {
+      Dictionary<string, double> coeffs;
+      double intercept;
+      do {
+        coeffs = DoRegression(pd, variables, variances, means, yMean, 1.0e-8, out intercept);
+        variables = DeselectColinear(variances, coeffs, yVariance, pd, variables);
+      }
+      while (coeffs.Count != variables.Count);
+      var numAtts = variables.Count;
+      var numInst = pd.TrainingIndices.Count();
+      var fullMse = CalculateSE(coeffs, intercept, pd, variables);
+      var akaike = 1.0 * (numInst - numAtts) + 2 * numAtts;
+
+      var improved = true;
+      var currentNumAttributes = numAtts;
+
+      while (improved && currentNumAttributes > 1) {
+        improved = false;
+        currentNumAttributes--;
+        // Find attribute with smallest SC (variance-scaled coefficient)
+        var candidate = variables.ToDictionary(v => v, v => Math.Abs(coeffs[v] * Math.Sqrt(variances[v] / yVariance)))
+          .OrderBy(x => x.Value).Select(x => x.Key).First();
+
+        var currVariables = variables.Where(v => !v.Equals(candidate)).ToList();
+        var currentIntercept = 0.0;
+        var currentCoeffs = DoRegression(pd, currVariables, variances, means, yMean, 1.0e-8, out currentIntercept);
+        var currentMse = CalculateSE(currentCoeffs, currentIntercept, pd, currVariables);
+        var currentAkaike = currentMse / fullMse * (numInst - numAtts) + 2 * currentNumAttributes;
+
+        if (!(currentAkaike < akaike)) continue;
+        improved = true;
+        akaike = currentAkaike;
+        coeffs = currentCoeffs;
+        intercept = currentIntercept;
+        variables = currVariables;
+      }
+
+      var pd2 = new RegressionProblemData(pd.Dataset, variables, pd.TargetVariable);
+      pd2.TestPartition.End = pd.TestPartition.End;
+      pd2.TestPartition.Start = pd.TestPartition.Start;
+      pd2.TrainingPartition.End = pd.TrainingPartition.End;
+      pd2.TrainingPartition.Start = pd.TrainingPartition.Start;
+
+      return new PreconstructedLinearModel(coeffs, intercept, pd.TargetVariable);
+    }
+
+    private static Dictionary<string, double> DoRegression(IRegressionProblemData pd, IList<string> variables, Dictionary<string, double> variances, Dictionary<string, double> means, double yMean, double ridge, out double intercept) {
+
+      var n = variables.Count;
+      var m = pd.TrainingIndices.Count();
+
+      var inTr = new double[n, m];
+      for (var i = 0; i < n; i++) {
+        var v = variables[i];
+        var vdata = pd.Dataset.GetDoubleValues(v, pd.TrainingIndices).ToArray();
+        var sd = Math.Sqrt(variances[v]);
+        var mean = means[v];
+        for (var j = 0; j < m; j++) {
+          inTr[i, j] = (vdata[j] - mean) / sd;
+        }
+      }
+
+      var y = new double[m, 1];
+      var ydata = pd.TargetVariableTrainingValues.ToArray();
+      for (var i = 0; i < m; i++)
+        y[i, 0] = ydata[i]; //no scaling for targets;
+
+
+      var aTy = new double[n, 1];
+      alglib.rmatrixgemm(n, 1, m, 1, inTr, 0, 0, 0, y, 0, 0, 0, 0, ref aTy, 0, 0); //aTy = inTr * y;
+      var aTa = new double[n, n];
+      alglib.rmatrixgemm(n, n, m, 1, inTr, 0, 0, 0, inTr, 0, 0, 1, 0, ref aTa, 0, 0); //aTa = inTr * t(inTr) +aTa //
+
+      var aTaDecomp = new double[n, n];
+      bool success;
+      var tries = 0;
+      double[] coefficients = null;
+      do {
+        for (var i = 0; i < n; i++) aTa[i, i] += ridge; // add ridge to diagonal to enforce singularity
+        try {
+          //solve "aTa * coefficients = aTy" for coefficients;
+          Array.Copy(aTa, 0, aTaDecomp, 0, aTa.Length);
+          alglib.spdmatrixcholesky(ref aTaDecomp, n, true);
+          int info;
+          alglib.densesolverreport report;
+          alglib.spdmatrixcholeskysolve(aTaDecomp, n, true, ydata, out info, out report, out coefficients);
+
+          if (info != 1) throw new Exception();
+          success = true;
+        }
+        catch (Exception) {
+          for (var i = 0; i < n; i++) aTa[i, i] -= ridge;
+          ridge *= 10; // increase ridge;
+          success = false;
+        }
+        finally {
+          tries++;
+        }
+      }
+      while (!success && tries < 100);
+      if (coefficients == null || coefficients.Length != n) throw new ArgumentException("No linear model could be built");
+
+      intercept = yMean;
+      var res = new Dictionary<string, double>();
+      for (var i = 0; i < n; i++) {
+        var v = variables[i];
+        res.Add(v, coefficients[i] /= Math.Sqrt(variances[v]));
+        intercept -= coefficients[i] * means[v];
+      }
+
+      return res;
+    }
+
+    private static IList<string> DeselectColinear(Dictionary<string, double> variances, Dictionary<string, double> coeffs, double yVariance, IRegressionProblemData pd, IList<string> variables) {
+      var candidates = variables.ToDictionary(v => v, v => Math.Abs(coeffs[v] * Math.Sqrt(variances[v] / yVariance))).Where(x => x.Value > 1.5).OrderBy(x => -x.Value).ToList();
+      if (candidates.Count == 0) return variables;
+      var c = candidates.First().Key;
+      return variables.Where(v => !v.Equals(c)).ToList();
+    }
+
+    private static double CalculateSE(Dictionary<string, double> coefficients, double intercept, IRegressionProblemData pd, IList<string> variables) {
+      return pd.TrainingIndices.Select(i => RegressionPrediction(i, pd, variables, coefficients, intercept) - pd.Dataset.GetDoubleValue(pd.TargetVariable, i)).Select(error => error * error).Sum();
+    }
+    private static double RegressionPrediction(int i, IRegressionProblemData pd, IList<string> variables, Dictionary<string, double> coefficients, double intercept) {
+      return intercept + variables.Sum(v => pd.Dataset.GetDoubleValue(v, i) * coefficients[v]);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/M5regLeaf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/M5regLeaf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/LeafTypes/M5regLeaf.cs	(revision 16892)
@@ -0,0 +1,64 @@
+﻿#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 System.Threading;
+using HeuristicLab.Algorithms.DataAnalysis.Glmnet;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("0AED959D-78C3-4927-BDCF-473D0AEE32AA")]
+  [Item("M5regLeaf", "A leaf type that uses regularized linear models as leaf models.")]
+  public sealed class M5regLeaf : LeafBase {
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private M5regLeaf(StorableConstructorFlag _) : base(_) { }
+    private M5regLeaf(M5regLeaf original, Cloner cloner) : base(original, cloner) { }
+    public M5regLeaf() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new M5regLeaf(this, cloner);
+    }
+    #endregion
+
+    #region IModelType
+    public override bool ProvidesConfidence {
+      get { return false; }
+    }
+
+    public override IRegressionModel Build(IRegressionProblemData pd, IRandom random, CancellationToken cancellationToken, out int numberOfParameters) {
+      if (pd.Dataset.Rows < MinLeafSize(pd)) throw new ArgumentException("The number of training instances is too small to create a linear model");
+      numberOfParameters = pd.AllowedInputVariables.Count() + 1;
+
+      double x1, x2;
+      var coeffs = ElasticNetLinearRegression.CalculateModelCoefficients(pd, 1, 0.2, out x1, out x2);
+      numberOfParameters = coeffs.Length;
+      return ElasticNetLinearRegression.CreateSymbolicSolution(coeffs, pd).Model;
+    }
+    public override int MinLeafSize(IRegressionProblemData pd) {
+      return pd.AllowedInputVariables.Count() + 2;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Regression.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Regression.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Regression.cs	(revision 16892)
@@ -0,0 +1,306 @@
+#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 System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Random;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("FC8D8E5A-D16D-41BB-91CF-B2B35D17ADD7")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 95)]
+  [Item("M5RegressionTree", "A M5 regression tree / rule set")]
+  public sealed class M5Regression : FixedDataAnalysisAlgorithm<IRegressionProblem> {
+    public override bool SupportsPause {
+      get { return true; }
+    }
+
+    public const string RegressionTreeParameterVariableName = "RegressionTreeParameters";
+    public const string ModelVariableName = "Model";
+    public const string PruningSetVariableName = "PruningSet";
+    public const string TrainingSetVariableName = "TrainingSet";
+
+    #region Parameter names
+    private const string GenerateRulesParameterName = "GenerateRules";
+    private const string HoldoutSizeParameterName = "HoldoutSize";
+    private const string SplitterParameterName = "Splitter";
+    private const string MinimalNodeSizeParameterName = "MinimalNodeSize";
+    private const string LeafModelParameterName = "LeafModel";
+    private const string PruningTypeParameterName = "PruningType";
+    private const string SeedParameterName = "Seed";
+    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
+    private const string UseHoldoutParameterName = "UseHoldout";
+    #endregion
+
+    #region Parameter properties
+    public IFixedValueParameter<BoolValue> GenerateRulesParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[GenerateRulesParameterName]; }
+    }
+    public IFixedValueParameter<PercentValue> HoldoutSizeParameter {
+      get { return (IFixedValueParameter<PercentValue>)Parameters[HoldoutSizeParameterName]; }
+    }
+    public IConstrainedValueParameter<ISplitter> SplitterParameter {
+      get { return (IConstrainedValueParameter<ISplitter>)Parameters[SplitterParameterName]; }
+    }
+    public IFixedValueParameter<IntValue> MinimalNodeSizeParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[MinimalNodeSizeParameterName]; }
+    }
+    public IConstrainedValueParameter<ILeafModel> LeafModelParameter {
+      get { return (IConstrainedValueParameter<ILeafModel>)Parameters[LeafModelParameterName]; }
+    }
+    public IConstrainedValueParameter<IPruning> PruningTypeParameter {
+      get { return (IConstrainedValueParameter<IPruning>)Parameters[PruningTypeParameterName]; }
+    }
+    public IFixedValueParameter<IntValue> SeedParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> UseHoldoutParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[UseHoldoutParameterName]; }
+    }
+    #endregion
+
+    #region Properties 
+    public bool GenerateRules {
+      get { return GenerateRulesParameter.Value.Value; }
+      set { GenerateRulesParameter.Value.Value = value; }
+    }
+    public double HoldoutSize {
+      get { return HoldoutSizeParameter.Value.Value; }
+      set { HoldoutSizeParameter.Value.Value = value; }
+    }
+    public ISplitter Splitter {
+      get { return SplitterParameter.Value; }
+      // no setter because this is a constrained parameter
+    }
+    public int MinimalNodeSize {
+      get { return MinimalNodeSizeParameter.Value.Value; }
+      set { MinimalNodeSizeParameter.Value.Value = value; }
+    }
+    public ILeafModel LeafModel {
+      get { return LeafModelParameter.Value; }
+    }
+    public IPruning Pruning {
+      get { return PruningTypeParameter.Value; }
+    }
+    public int Seed {
+      get { return SeedParameter.Value.Value; }
+      set { SeedParameter.Value.Value = value; }
+    }
+    public bool SetSeedRandomly {
+      get { return SetSeedRandomlyParameter.Value.Value; }
+      set { SetSeedRandomlyParameter.Value.Value = value; }
+    }
+    public bool UseHoldout {
+      get { return UseHoldoutParameter.Value.Value; }
+      set { UseHoldoutParameter.Value.Value = value; }
+    }
+    #endregion
+
+    #region State
+    [Storable]
+    private IScope stateScope;
+    #endregion
+
+    #region Constructors and Cloning
+    [StorableConstructor]
+    private M5Regression(StorableConstructorFlag _) : base(_) { }
+    private M5Regression(M5Regression original, Cloner cloner) : base(original, cloner) {
+      stateScope = cloner.Clone(stateScope);
+    }
+    public M5Regression() {
+      var modelSet = new ItemSet<ILeafModel>(ApplicationManager.Manager.GetInstances<ILeafModel>());
+      var pruningSet = new ItemSet<IPruning>(ApplicationManager.Manager.GetInstances<IPruning>());
+      var splitterSet = new ItemSet<ISplitter>(ApplicationManager.Manager.GetInstances<ISplitter>());
+      Parameters.Add(new FixedValueParameter<BoolValue>(GenerateRulesParameterName, "Whether a set of rules or a decision tree shall be created (default=false)", new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<PercentValue>(HoldoutSizeParameterName, "How much of the training set shall be reserved for pruning (default=20%).", new PercentValue(0.2)));
+      Parameters.Add(new ConstrainedValueParameter<ISplitter>(SplitterParameterName, "The type of split function used to create node splits (default='M5Splitter').", splitterSet, splitterSet.OfType<M5Splitter>().First()));
+      Parameters.Add(new FixedValueParameter<IntValue>(MinimalNodeSizeParameterName, "The minimal number of samples in a leaf node (default=1).", new IntValue(1)));
+      Parameters.Add(new ConstrainedValueParameter<ILeafModel>(LeafModelParameterName, "The type of model used for the nodes (default='LinearLeaf').", modelSet, modelSet.OfType<LinearLeaf>().First()));
+      Parameters.Add(new ConstrainedValueParameter<IPruning>(PruningTypeParameterName, "The type of pruning used (default='ComplexityPruning').", pruningSet, pruningSet.OfType<ComplexityPruning>().First()));
+      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(UseHoldoutParameterName, "True if a holdout set should be generated, false if splitting and pruning shall be performed on the same data (default=false).", new BoolValue(false)));
+      Problem = new RegressionProblem();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new M5Regression(this, cloner);
+    }
+    #endregion
+
+    protected override void Initialize(CancellationToken cancellationToken) {
+      base.Initialize(cancellationToken);
+      var random = new MersenneTwister();
+      if (SetSeedRandomly) Seed = RandomSeedGenerator.GetSeed();
+      random.Reset(Seed);
+      stateScope = InitializeScope(random, Problem.ProblemData, Pruning, MinimalNodeSize, LeafModel, Splitter, GenerateRules, UseHoldout, HoldoutSize);
+      stateScope.Variables.Add(new Variable("Algorithm", this));
+      Results.AddOrUpdateResult("StateScope", stateScope);
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      var model = Build(stateScope, Results, cancellationToken);
+      AnalyzeSolution(model.CreateRegressionSolution(Problem.ProblemData), Results, Problem.ProblemData);
+    }
+
+    #region Static Interface
+    public static IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData, IRandom random, ILeafModel leafModel = null, ISplitter splitter = null, IPruning pruning = null,
+      bool useHoldout = false, double holdoutSize = 0.2, int minimumLeafSize = 1, bool generateRules = false, ResultCollection results = null, CancellationToken? cancellationToken = null) {
+      if (leafModel == null) leafModel = new LinearLeaf();
+      if (splitter == null) splitter = new M5Splitter();
+      if (cancellationToken == null) cancellationToken = CancellationToken.None;
+      if (pruning == null) pruning = new ComplexityPruning();
+
+      var stateScope = InitializeScope(random, problemData, pruning, minimumLeafSize, leafModel, splitter, generateRules, useHoldout, holdoutSize);
+      var model = Build(stateScope, results, cancellationToken.Value);
+      return model.CreateRegressionSolution(problemData);
+    }
+
+    public static void UpdateModel(IM5Model model, IRegressionProblemData problemData, IRandom random, ILeafModel leafModel, CancellationToken? cancellationToken = null) {
+      if (cancellationToken == null) cancellationToken = CancellationToken.None;
+      var regressionTreeParameters = new RegressionTreeParameters(leafModel, problemData, random);
+      var scope = new Scope();
+      scope.Variables.Add(new Variable(RegressionTreeParameterVariableName, regressionTreeParameters));
+      leafModel.Initialize(scope);
+      model.Update(problemData.TrainingIndices.ToList(), scope, cancellationToken.Value);
+    }
+    #endregion
+
+    #region Helpers
+    private static IScope InitializeScope(IRandom random, IRegressionProblemData problemData, IPruning pruning, int minLeafSize, ILeafModel leafModel, ISplitter splitter, bool generateRules, bool useHoldout, double holdoutSize) {
+      var stateScope = new Scope("RegressionTreeStateScope");
+
+      //reduce RegressionProblemData to AllowedInput & Target column wise and to TrainingSet row wise
+      var doubleVars = new HashSet<string>(problemData.Dataset.DoubleVariables);
+      var vars = problemData.AllowedInputVariables.Concat(new[] {problemData.TargetVariable}).ToArray();
+      if (vars.Any(v => !doubleVars.Contains(v))) throw new NotSupportedException("M5 regression supports only double valued input or output features.");
+      var doubles = vars.Select(v => problemData.Dataset.GetDoubleValues(v, problemData.TrainingIndices).ToArray()).ToArray();
+      if (doubles.Any(v => v.Any(x => double.IsNaN(x) || double.IsInfinity(x))))
+        throw new NotSupportedException("M5 regression does not support NaN or infinity values in the input dataset.");
+      var trainingData = new Dataset(vars, doubles);
+      var pd = new RegressionProblemData(trainingData, problemData.AllowedInputVariables, problemData.TargetVariable);
+      pd.TrainingPartition.End = pd.TestPartition.Start = pd.TestPartition.End = pd.Dataset.Rows;
+      pd.TrainingPartition.Start = 0;
+
+      //store regression tree parameters
+      var regressionTreeParams = new RegressionTreeParameters(pruning, minLeafSize, leafModel, pd, random, splitter);
+      stateScope.Variables.Add(new Variable(RegressionTreeParameterVariableName, regressionTreeParams));
+
+      //initialize tree operators
+      pruning.Initialize(stateScope);
+      splitter.Initialize(stateScope);
+      leafModel.Initialize(stateScope);
+
+      //store unbuilt model
+      IItem model;
+      if (generateRules) {
+        model = RegressionRuleSetModel.CreateRuleModel(problemData.TargetVariable, regressionTreeParams);
+        RegressionRuleSetModel.Initialize(stateScope);
+      }
+      else {
+        model = RegressionNodeTreeModel.CreateTreeModel(problemData.TargetVariable, regressionTreeParams);
+      }
+      stateScope.Variables.Add(new Variable(ModelVariableName, model));
+
+      //store training & pruning indices
+      IReadOnlyList<int> trainingSet, pruningSet;
+      GeneratePruningSet(pd.TrainingIndices.ToArray(), random, useHoldout, holdoutSize, out trainingSet, out pruningSet);
+      stateScope.Variables.Add(new Variable(TrainingSetVariableName, new IntArray(trainingSet.ToArray())));
+      stateScope.Variables.Add(new Variable(PruningSetVariableName, new IntArray(pruningSet.ToArray())));
+
+      return stateScope;
+    }
+
+    private static IRegressionModel Build(IScope stateScope, ResultCollection results, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)stateScope.Variables[RegressionTreeParameterVariableName].Value;
+      var model = (IM5Model)stateScope.Variables[ModelVariableName].Value;
+      var trainingRows = (IntArray)stateScope.Variables[TrainingSetVariableName].Value;
+      var pruningRows = (IntArray)stateScope.Variables[PruningSetVariableName].Value;
+      if (1 > trainingRows.Length)
+        return new PreconstructedLinearModel(new Dictionary<string, double>(), 0, regressionTreeParams.TargetVariable);
+      if (regressionTreeParams.MinLeafSize > trainingRows.Length) {
+        var targets = regressionTreeParams.Data.GetDoubleValues(regressionTreeParams.TargetVariable).ToArray();
+        return new PreconstructedLinearModel(new Dictionary<string, double>(), targets.Average(), regressionTreeParams.TargetVariable);
+      }
+      model.Build(trainingRows.ToArray(), pruningRows.ToArray(), stateScope, results, cancellationToken);
+      return model;
+    }
+
+    private static void GeneratePruningSet(IReadOnlyList<int> allrows, IRandom random, bool useHoldout, double holdoutSize, out IReadOnlyList<int> training, out IReadOnlyList<int> pruning) {
+      if (!useHoldout) {
+        training = allrows;
+        pruning = allrows;
+        return;
+      }
+      var perm = new Permutation(PermutationTypes.Absolute, allrows.Count, random);
+      var cut = (int)(holdoutSize * allrows.Count);
+      pruning = perm.Take(cut).Select(i => allrows[i]).ToArray();
+      training = perm.Take(cut).Select(i => allrows[i]).ToArray();
+    }
+
+    private void AnalyzeSolution(IRegressionSolution solution, ResultCollection results, IRegressionProblemData problemData) {
+      results.Add(new Result("RegressionSolution", (IItem)solution.Clone()));
+
+      Dictionary<string, int> frequencies = null;
+
+      var tree = solution.Model as RegressionNodeTreeModel;
+      if (tree != null) {
+        results.Add(RegressionTreeAnalyzer.CreateLeafDepthHistogram(tree));
+        frequencies = RegressionTreeAnalyzer.GetTreeVariableFrequences(tree);
+        RegressionTreeAnalyzer.AnalyzeNodes(tree, results, problemData);
+      }
+
+      var ruleSet = solution.Model as RegressionRuleSetModel;
+      if (ruleSet != null) {
+        results.Add(RegressionTreeAnalyzer.CreateRulesResult(ruleSet, problemData, "M5Rules", true));
+        frequencies = RegressionTreeAnalyzer.GetRuleVariableFrequences(ruleSet);
+        results.Add(RegressionTreeAnalyzer.CreateCoverageDiagram(ruleSet, problemData));
+      }
+
+      //Variable frequencies
+      if (frequencies != null) {
+        var sum = frequencies.Values.Sum();
+        sum = sum == 0 ? 1 : sum;
+        var impactArray = new DoubleArray(frequencies.Select(i => (double)i.Value / sum).ToArray()) {
+          ElementNames = frequencies.Select(i => i.Key)
+        };
+        results.Add(new Result("Variable Frequences", "relative frequencies of variables in rules and tree nodes", impactArray));
+      }
+
+      var pruning = Pruning as ComplexityPruning;
+      if (pruning != null && tree != null)
+        RegressionTreeAnalyzer.PruningChart(tree, pruning, results);
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/PrincipleComponentTransformation.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/PrincipleComponentTransformation.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/PrincipleComponentTransformation.cs	(revision 16892)
@@ -0,0 +1,200 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("A2DDC528-BAA7-445F-98E1-5F895CE2FD5C")]
+  public class PrincipleComponentTransformation : IDeepCloneable {
+    #region Properties
+    [Storable]
+    private double[,] Matrix { get; set; }
+    [Storable]
+    public double[] Variances { get; private set; }
+    [Storable]
+    public string[] VariableNames { get; private set; }
+    [Storable]
+    private double[] Deviations { get; set; }
+    [Storable]
+    private double[] Means { get; set; }
+    public string[] ComponentNames {
+      get { return VariableNames.Select((_, x) => "pc" + x).ToArray(); }
+    }
+    #endregion
+
+    #region HLConstructors
+    [StorableConstructor]
+    protected PrincipleComponentTransformation(StorableConstructorFlag _) { }
+    protected PrincipleComponentTransformation(PrincipleComponentTransformation original, Cloner cloner) {
+      if (original.Variances != null) Variances = original.Variances.ToArray();
+      if (original.VariableNames != null) VariableNames = original.VariableNames.ToArray();
+      if (original.Deviations != null) Deviations = original.Deviations.ToArray();
+      if (original.Means != null) Means = original.Means.ToArray();
+      if (original.Matrix == null) return;
+      Matrix = new double[original.Matrix.GetLength(0), original.Matrix.GetLength(1)];
+      for (var i = 0; i < original.Matrix.GetLength(0); i++)
+      for (var j = 0; j < original.Matrix.GetLength(1); j++)
+        Matrix[i, j] = original.Matrix[i, j];
+    }
+    private PrincipleComponentTransformation() { }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new PrincipleComponentTransformation(this, cloner);
+    }
+    public object Clone() {
+      return new Cloner().Clone(this);
+    }
+    #endregion
+
+    #region Static Interface
+    public static PrincipleComponentTransformation CreateProjection(IDataset dataset, IEnumerable<int> rows, IEnumerable<string> variables, bool normalize = false) {
+      var res = new PrincipleComponentTransformation();
+      res.BuildPca(dataset, rows, variables, normalize);
+      return res;
+    }
+    #endregion
+
+    #region Projection
+    public IRegressionProblemData TransformProblemData(IRegressionProblemData pd) {
+      return CreateProblemData(pd, TransformDataset(pd.Dataset), ComponentNames);
+    }
+
+    public IDataset TransformDataset(IDataset data) {
+      return CreateDataset(data, TransformData(data, Enumerable.Range(0, data.Rows)));
+    }
+
+    public double[,] TransformData(IDataset dataset, IEnumerable<int> rows) {
+      var instances = rows.ToArray();
+      var result = new double[instances.Length, VariableNames.Length];
+      for (var r = 0; r < instances.Length; r++)
+      for (var i = 0; i < VariableNames.Length; i++) {
+        var val = (dataset.GetDoubleValue(VariableNames[i], instances[r]) - Means[i]) / Deviations[i];
+        for (var j = 0; j < VariableNames.Length; j++)
+          result[r, j] += val * Matrix[i, j];
+      }
+      return result;
+    }
+    #endregion
+
+    #region Reversion
+    public IRegressionProblemData RevertProblemData(IRegressionProblemData pd) {
+      return CreateProblemData(pd, RevertDataset(pd.Dataset), VariableNames);
+    }
+
+    public IDataset RevertDataset(IDataset data) {
+      return CreateRevertedDataset(data, RevertData(data, Enumerable.Range(0, data.Rows)));
+    }
+
+    public double[,] RevertData(IDataset dataset, IEnumerable<int> rows) {
+      var instances = rows.ToArray();
+      var components = ComponentNames;
+      var result = new double[instances.Length, VariableNames.Length];
+      for (var r = 0; r < instances.Length; r++)
+      for (var i = 0; i < components.Length; i++) {
+        var val = dataset.GetDoubleValue(components[i], instances[r]);
+        for (var j = 0; j < VariableNames.Length; j++)
+          result[r, j] += val * Matrix[j, i];
+      }
+      for (var r = 0; r < instances.Length; r++) {
+        for (var j = 0; j < VariableNames.Length; j++) {
+          result[r, j] *= Deviations[j];
+          result[r, j] += Means[j];
+        }
+      }
+
+      return result;
+    }
+    #endregion
+
+    #region Helpers
+    private static IRegressionProblemData CreateProblemData(IRegressionProblemData pd, IDataset data, IReadOnlyList<string> allowedNames) {
+      var res = new RegressionProblemData(data, allowedNames, pd.TargetVariable);
+      res.TestPartition.Start = pd.TestPartition.Start;
+      res.TestPartition.End = pd.TestPartition.End;
+      res.TrainingPartition.Start = pd.TrainingPartition.Start;
+      res.TrainingPartition.End = pd.TrainingPartition.End;
+      res.Name = pd.Name;
+      return res;
+    }
+
+    private IDataset CreateDataset(IDataset data, double[,] pcs) {
+      var n = ComponentNames;
+      var nDouble = data.DoubleVariables.Where(x => !VariableNames.Contains(x)).ToArray();
+      var nDateTime = data.DateTimeVariables.ToArray();
+      var nString = data.StringVariables.ToArray();
+
+      IEnumerable<IList> nData = n.Select((_, x) => Enumerable.Range(0, pcs.GetLength(0)).Select(r => pcs[r, x]).ToList());
+      IEnumerable<IList> nDoubleData = nDouble.Select(x => data.GetDoubleValues(x).ToList());
+      IEnumerable<IList> nDateTimeData = nDateTime.Select(x => data.GetDateTimeValues(x).ToList());
+      IEnumerable<IList> nStringData = nString.Select(x => data.GetStringValues(x).ToList());
+
+      return new Dataset(n.Concat(nDouble).Concat(nDateTime).Concat(nString), nData.Concat(nDoubleData).Concat(nDateTimeData).Concat(nStringData).ToArray());
+    }
+
+    private IDataset CreateRevertedDataset(IDataset data, double[,] pcs) {
+      var n = VariableNames;
+      var nDouble = data.DoubleVariables.Where(x => !ComponentNames.Contains(x)).ToArray();
+      var nDateTime = data.DateTimeVariables.ToArray();
+      var nString = data.StringVariables.ToArray();
+
+      IEnumerable<IList> nData = n.Select((_, x) => Enumerable.Range(0, pcs.GetLength(0)).Select(r => pcs[r, x]).ToList());
+      IEnumerable<IList> nDoubleData = nDouble.Select(x => data.GetDoubleValues(x).ToList());
+      IEnumerable<IList> nDateTimeData = nDateTime.Select(x => data.GetDateTimeValues(x).ToList());
+      IEnumerable<IList> nStringData = nString.Select(x => data.GetStringValues(x).ToList());
+
+      return new Dataset(n.Concat(nDouble).Concat(nDateTime).Concat(nString), nData.Concat(nDoubleData).Concat(nDateTimeData).Concat(nStringData).ToArray());
+    }
+
+    private void BuildPca(IDataset dataset, IEnumerable<int> rows, IEnumerable<string> variables, bool normalize) {
+      var instances = rows.ToArray();
+      var attributes = variables.ToArray();
+      Means = normalize
+        ? attributes.Select(v => dataset.GetDoubleValues(v, instances).Average()).ToArray()
+        : attributes.Select(x => 0.0).ToArray();
+      Deviations = normalize
+        ? attributes.Select(v => dataset.GetDoubleValues(v, instances).StandardDeviationPop()).Select(x => x.IsAlmost(0.0) ? 1 : x).ToArray()
+        : attributes.Select(x => 1.0).ToArray();
+
+      var data = new double[instances.Length, attributes.Length];
+
+      for (var j = 0; j < attributes.Length; j++) {
+        var i = 0;
+        foreach (var v in dataset.GetDoubleValues(attributes[j], instances)) {
+          data[i, j] = (v - Means[j]) / Deviations[j];
+          i++;
+        }
+      }
+
+      int info;
+      double[] variances;
+      double[,] matrix;
+      alglib.pcabuildbasis(data, instances.Length, attributes.Length, out info, out variances, out matrix);
+      Matrix = matrix;
+      Variances = variances;
+      VariableNames = attributes;
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeAnalyzer.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeAnalyzer.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeAnalyzer.cs	(revision 16892)
@@ -0,0 +1,266 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  public static class RegressionTreeAnalyzer {
+    private const string ConditionResultName = "Condition";
+    private const string CoverResultName = "Covered Instances";
+    private const string CoverageDiagramResultName = "Coverage";
+    private const string RuleModelResultName = "RuleModel";
+
+    public static Dictionary<string, int> GetRuleVariableFrequences(RegressionRuleSetModel ruleSetModel) {
+      var res = ruleSetModel.VariablesUsedForPrediction.ToDictionary(x => x, x => 0);
+      foreach (var rule in ruleSetModel.Rules)
+      foreach (var att in rule.SplitAttributes)
+        res[att]++;
+      return res;
+    }
+
+    public static Dictionary<string, int> GetTreeVariableFrequences(RegressionNodeTreeModel treeModel) {
+      var res = treeModel.VariablesUsedForPrediction.ToDictionary(x => x, x => 0);
+      var root = treeModel.Root;
+      foreach (var cur in root.EnumerateNodes().Where(x => !x.IsLeaf))
+        res[cur.SplitAttribute]++;
+      return res;
+    }
+
+    public static Result CreateLeafDepthHistogram(RegressionNodeTreeModel treeModel) {
+      var list = new List<int>();
+      GetLeafDepths(treeModel.Root, 0, list);
+      var row = new DataRow("Depths", "", list.Select(x => (double)x)) {
+        VisualProperties = {ChartType = DataRowVisualProperties.DataRowChartType.Histogram}
+      };
+      var hist = new DataTable("LeafDepths");
+      hist.Rows.Add(row);
+      return new Result(hist.Name, hist);
+    }
+
+    public static Result CreateRulesResult(RegressionRuleSetModel ruleSetModel, IRegressionProblemData pd, string resultName, bool displayModels) {
+      var res = new ResultCollection();
+      var i = 0;
+      foreach (var rule in ruleSetModel.Rules)
+        res.Add(new Result("Rule" + i++, CreateRulesResult(rule, pd, displayModels, out pd)));
+      return new Result(resultName, res);
+    }
+
+    public static IResult CreateCoverageDiagram(RegressionRuleSetModel setModel, IRegressionProblemData problemData) {
+      var res = new DataTable(CoverageDiagramResultName);
+      var training = CountCoverage(setModel, problemData.Dataset, problemData.TrainingIndices);
+      var test = CountCoverage(setModel, problemData.Dataset, problemData.TestIndices);
+      res.Rows.Add(new DataRow("Training", "", training));
+      res.Rows.Add(new DataRow("Test", "", test));
+
+      foreach (var row in res.Rows)
+        row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Columns;
+      res.VisualProperties.XAxisMaximumFixedValue = training.Count + 1;
+      res.VisualProperties.XAxisMaximumAuto = false;
+      res.VisualProperties.XAxisMinimumFixedValue = 0;
+      res.VisualProperties.XAxisMinimumAuto = false;
+      res.VisualProperties.XAxisTitle = "Rule";
+      res.VisualProperties.YAxisTitle = "Covered Instances";
+
+      return new Result(CoverageDiagramResultName, res);
+    }
+
+    private static void GetLeafDepths(RegressionNodeModel n, int depth, ICollection<int> res) {
+      if (n == null) return;
+      if (n.Left == null && n.Right == null) res.Add(depth);
+      else {
+        GetLeafDepths(n.Left, depth + 1, res);
+        GetLeafDepths(n.Right, depth + 1, res);
+      }
+    }
+
+    private static IScope CreateRulesResult(RegressionRuleModel regressionRuleModel, IRegressionProblemData pd, bool displayModels, out IRegressionProblemData notCovered) {
+      var training = pd.TrainingIndices.Where(x => !regressionRuleModel.Covers(pd.Dataset, x)).ToArray();
+      var test = pd.TestIndices.Where(x => !regressionRuleModel.Covers(pd.Dataset, x)).ToArray();
+      if (training.Length > 0 || test.Length > 0) {
+        var data = new Dataset(pd.Dataset.DoubleVariables, pd.Dataset.DoubleVariables.Select(v => pd.Dataset.GetDoubleValues(v, training.Concat(test)).ToArray()));
+        notCovered = new RegressionProblemData(data, pd.AllowedInputVariables, pd.TargetVariable);
+        notCovered.TestPartition.Start = notCovered.TrainingPartition.End = training.Length;
+        notCovered.TestPartition.End = training.Length + test.Length;
+      } else notCovered = null;
+
+      var training2 = pd.TrainingIndices.Where(x => regressionRuleModel.Covers(pd.Dataset, x)).ToArray();
+      var test2 = pd.TestIndices.Where(x => regressionRuleModel.Covers(pd.Dataset, x)).ToArray();
+      var data2 = new Dataset(pd.Dataset.DoubleVariables, pd.Dataset.DoubleVariables.Select(v => pd.Dataset.GetDoubleValues(v, training2.Concat(test2)).ToArray()));
+      var covered = new RegressionProblemData(data2, pd.AllowedInputVariables, pd.TargetVariable);
+      covered.TestPartition.Start = covered.TrainingPartition.End = training2.Length;
+      covered.TestPartition.End = training2.Length + test2.Length;
+
+      var res2 = new Scope("RuleModels");
+      res2.Variables.Add(new Variable(ConditionResultName, new StringValue(regressionRuleModel.ToCompactString())));
+      res2.Variables.Add(new Variable(CoverResultName, new IntValue(pd.TrainingIndices.Count() - training.Length)));
+      if (displayModels)
+        res2.Variables.Add(new Variable(RuleModelResultName, regressionRuleModel.CreateRegressionSolution(covered)));
+      return res2;
+    }
+
+    private static IReadOnlyList<double> CountCoverage(RegressionRuleSetModel setModel, IDataset data, IEnumerable<int> rows) {
+      var rules = setModel.Rules.ToArray();
+      var res = new double[rules.Length];
+      foreach (var row in rows)
+        for (var i = 0; i < rules.Length; i++)
+          if (rules[i].Covers(data, row)) {
+            res[i]++;
+            break;
+          }
+      return res;
+    }
+
+    public static void AnalyzeNodes(RegressionNodeTreeModel tree, ResultCollection results, IRegressionProblemData pd) {
+      var dict = new Dictionary<int, RegressionNodeModel>();
+      var trainingLeafRows = new Dictionary<int, IReadOnlyList<int>>();
+      var testLeafRows = new Dictionary<int, IReadOnlyList<int>>();
+      var modelNumber = new IntValue(1);
+      var symtree = new SymbolicExpressionTree(MirrorTree(tree.Root, dict, trainingLeafRows, testLeafRows, modelNumber, pd.Dataset, pd.TrainingIndices.ToList(), pd.TestIndices.ToList()));
+      results.AddOrUpdateResult("DecisionTree", symtree);
+
+      if (dict.Count > 200) return;
+      var models = new Scope("NodeModels");
+      results.AddOrUpdateResult("NodeModels", models);
+      foreach (var m in dict.Keys.OrderBy(x => x))
+        models.Variables.Add(new Variable("Model " + m, dict[m].CreateRegressionSolution(Subselect(pd, trainingLeafRows[m], testLeafRows[m]))));
+    }
+
+    public static void PruningChart(RegressionNodeTreeModel tree, ComplexityPruning pruning, ResultCollection results) {
+      var nodes = new Queue<RegressionNodeModel>();
+      nodes.Enqueue(tree.Root);
+      var max = 0.0;
+      var strenghts = new SortedList<double, int>();
+      while (nodes.Count > 0) {
+        var n = nodes.Dequeue();
+
+        if (n.IsLeaf) {
+          max++;
+          continue;
+        }
+
+        if (!strenghts.ContainsKey(n.PruningStrength)) strenghts.Add(n.PruningStrength, 0);
+        strenghts[n.PruningStrength]++;
+        nodes.Enqueue(n.Left);
+        nodes.Enqueue(n.Right);
+      }
+      if (strenghts.Count == 0) return;
+
+      var plot = new ScatterPlot("Pruned Sizes", "") {
+        VisualProperties = {
+          XAxisTitle = "Pruning Strength",
+          YAxisTitle = "Tree Size",
+          XAxisMinimumAuto = false,
+          XAxisMinimumFixedValue = 0
+        }
+      };
+      var row = new ScatterPlotDataRow("TreeSizes", "", new List<Point2D<double>>());
+      row.Points.Add(new Point2D<double>(pruning.PruningStrength, max));
+
+      var fillerDots = new Queue<double>();
+      var minX = pruning.PruningStrength;
+      var maxX = strenghts.Last().Key;
+      var size = (maxX - minX) / 200;
+      for (var x = minX; x <= maxX; x += size) {
+        fillerDots.Enqueue(x);
+      }
+
+      foreach (var strenght in strenghts.Keys) {
+        while (fillerDots.Count > 0 && strenght > fillerDots.Peek())
+          row.Points.Add(new Point2D<double>(fillerDots.Dequeue(), max));
+        max -= strenghts[strenght];
+        row.Points.Add(new Point2D<double>(strenght, max));
+      }
+
+
+      row.VisualProperties.PointSize = 6;
+      plot.Rows.Add(row);
+      results.AddOrUpdateResult("PruningSizes", plot);
+    }
+
+
+    private static IRegressionProblemData Subselect(IRegressionProblemData data, IReadOnlyList<int> training, IReadOnlyList<int> test) {
+      var dataset = RegressionTreeUtilities.ReduceDataset(data.Dataset, training.Concat(test).ToList(), data.AllowedInputVariables.ToList(), data.TargetVariable);
+      var res = new RegressionProblemData(dataset, data.AllowedInputVariables, data.TargetVariable);
+      res.TrainingPartition.Start = 0;
+      res.TrainingPartition.End = training.Count;
+      res.TestPartition.Start = training.Count;
+      res.TestPartition.End = training.Count + test.Count;
+      return res;
+    }
+
+    private static SymbolicExpressionTreeNode MirrorTree(RegressionNodeModel regressionNode, IDictionary<int, RegressionNodeModel> dict,
+      IDictionary<int, IReadOnlyList<int>> trainingLeafRows,
+      IDictionary<int, IReadOnlyList<int>> testLeafRows,
+      IntValue nextId, IDataset data, IReadOnlyList<int> trainingRows, IReadOnlyList<int> testRows) {
+      if (regressionNode.IsLeaf) {
+        var i = nextId.Value++;
+        dict.Add(i, regressionNode);
+        trainingLeafRows.Add(i, trainingRows);
+        testLeafRows.Add(i, testRows);
+        return new SymbolicExpressionTreeNode(new TextSymbol("Model " + i + "\n(" + trainingRows.Count + "/" + testRows.Count + ")"));
+      }
+
+      var pftext = "\npf = " + regressionNode.PruningStrength.ToString("0.###");
+      var text = regressionNode.SplitAttribute + " <= " + regressionNode.SplitValue.ToString("0.###");
+      if (!double.IsNaN(regressionNode.PruningStrength)) text += pftext;
+
+      var textNode = new SymbolicExpressionTreeNode(new TextSymbol(text));
+      IReadOnlyList<int> lTrainingRows, rTrainingRows;
+      IReadOnlyList<int> lTestRows, rTestRows;
+      RegressionTreeUtilities.SplitRows(trainingRows, data, regressionNode.SplitAttribute, regressionNode.SplitValue, out lTrainingRows, out rTrainingRows);
+      RegressionTreeUtilities.SplitRows(testRows, data, regressionNode.SplitAttribute, regressionNode.SplitValue, out lTestRows, out rTestRows);
+
+      textNode.AddSubtree(MirrorTree(regressionNode.Left, dict, trainingLeafRows, testLeafRows, nextId, data, lTrainingRows, lTestRows));
+      textNode.AddSubtree(MirrorTree(regressionNode.Right, dict, trainingLeafRows, testLeafRows, nextId, data, rTrainingRows, rTestRows));
+
+      return textNode;
+    }
+
+
+    [StorableType("D5540C63-310B-4D6F-8A3D-6C1A08DE7F80")]
+    private sealed class TextSymbol : Symbol {
+      [StorableConstructor]
+      private TextSymbol(StorableConstructorFlag _) : base(_) { }
+      private TextSymbol(Symbol original, Cloner cloner) : base(original, cloner) { }
+      public TextSymbol(string name) : base(name, "") {
+        Name = name;
+      }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new TextSymbol(this, cloner);
+      }
+      public override int MinimumArity {
+        get { return 0; }
+      }
+      public override int MaximumArity {
+        get { return int.MaxValue; }
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeParameters.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeParameters.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeParameters.cs	(revision 16892)
@@ -0,0 +1,97 @@
+﻿#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.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("A6293516-C146-469D-B248-31B866A1D94F")]
+  public sealed class RegressionTreeParameters : Item {
+    private readonly ISplitter splitter;
+    private readonly IPruning pruning;
+    private readonly ILeafModel leafModel;
+    private readonly int minLeafSize;
+    private readonly IRegressionProblemData problemData;
+    private readonly IRandom random;
+    public ISplitter Splitter {
+      get { return splitter; }
+    }
+    public IPruning Pruning {
+      get { return pruning; }
+    }
+    public ILeafModel LeafModel {
+      get { return leafModel; }
+    }
+    public int MinLeafSize {
+      get { return minLeafSize; }
+    }
+    private IRegressionProblemData ProblemData {
+      get { return problemData; }
+    }
+    public IRandom Random {
+      get { return random; }
+    }
+    public IEnumerable<string> AllowedInputVariables {
+      get { return ProblemData.AllowedInputVariables; }
+    }
+    public string TargetVariable {
+      get { return ProblemData.TargetVariable; }
+    }
+    public IDataset Data {
+      get { return ProblemData.Dataset; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private RegressionTreeParameters(StorableConstructorFlag _) : base(_) { }
+    private RegressionTreeParameters(RegressionTreeParameters original, Cloner cloner) : base(original, cloner) {
+      problemData = cloner.Clone(original.problemData);
+      random = cloner.Clone(original.random);
+      leafModel = cloner.Clone(original.leafModel);
+      splitter = cloner.Clone(original.splitter);
+      pruning = cloner.Clone(original.pruning);
+      minLeafSize = original.minLeafSize;
+    }
+
+    public RegressionTreeParameters(IPruning pruning, int minleafSize, ILeafModel leafModel,
+      IRegressionProblemData problemData, IRandom random, ISplitter splitter) {
+      this.problemData = problemData;
+      this.random = random;
+      this.leafModel = leafModel;
+      this.splitter = splitter;
+      this.pruning = pruning;
+      minLeafSize = Math.Max(pruning.MinLeafSize(problemData, leafModel), Math.Max(minleafSize, leafModel.MinLeafSize(problemData)));
+    }
+    public RegressionTreeParameters(ILeafModel modeltype, IRegressionProblemData problemData, IRandom random) {
+      this.problemData = problemData;
+      this.random = random;
+      leafModel = modeltype;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionTreeParameters(this, cloner);
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeUtilities.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeUtilities.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/M5Utilities/RegressionTreeUtilities.cs	(revision 16892)
@@ -0,0 +1,61 @@
+#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  internal static class RegressionTreeUtilities {
+    public static ResultCollection RunSubAlgorithm(IAlgorithm alg, int random, CancellationToken cancellationToken) {
+      if (alg.Parameters.ContainsKey("SetSeedRandomly") && alg.Parameters.ContainsKey("Seed")) {
+        var seed = alg.Parameters["Seed"].ActualValue as IntValue;
+        var setSeed = alg.Parameters["SetSeedRandomly"].ActualValue as BoolValue;
+        if (seed == null || setSeed == null)
+          throw new ArgumentException("The parameters SetSeedRandomly and Seed do not have the expected type");
+        setSeed.Value = false;
+        seed.Value = random;
+      }
+      if (alg.ExecutionState != ExecutionState.Paused) alg.Prepare();
+      alg.Start(cancellationToken);
+      var res = alg.Results;
+      alg.Runs.Clear();
+      return res;
+    }
+
+    public static void SplitRows(IReadOnlyList<int> rows, IDataset data, string splitAttr, double splitValue, out IReadOnlyList<int> leftRows, out IReadOnlyList<int> rightRows) {
+      //TODO check and revert?: points at borders are now used multipe times
+      var assignment = data.GetDoubleValues(splitAttr, rows).Select(x => x.IsAlmost(splitValue) ? 2 : x < splitValue ? 0 : 1).ToArray();
+      leftRows = rows.Zip(assignment, (i, b) => new {i, b}).Where(x => x.b == 0 || x.b == 2).Select(x => x.i).ToList();
+      rightRows = rows.Zip(assignment, (i, b) => new {i, b}).Where(x => x.b > 0).Select(x => x.i).ToList();
+    }
+
+    public static IDataset ReduceDataset(IDataset data, IReadOnlyList<int> rows, IReadOnlyList<string> inputVariables, string target) {
+      return new Dataset(inputVariables.Concat(new[] {target}), inputVariables.Concat(new[] {target}).Select(x => data.GetDoubleValues(x, rows).ToList()));
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionNodeModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionNodeModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionNodeModel.cs	(revision 16892)
@@ -0,0 +1,175 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;                                                  
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("C20C7DF1-CE33-4CCD-88D3-E145CFE239AC")]
+  public class RegressionNodeModel : RegressionModel {
+    #region Properties
+    public double PruningStrength = double.NaN;
+    private IReadOnlyList<string> Variables {
+      get {
+        if (IsLeaf && Model == null) return new List<string>();
+        if (IsLeaf) return Model.VariablesUsedForPrediction.ToList();
+        var set = new HashSet<string> {SplitAttribute};
+        var vl = Left.Variables;
+        var vr = Right.Variables;
+        for (var i = 0; i < vl.Count; i++) set.Add(vl[i]);
+        for (var i = 0; i < vr.Count; i++) set.Add(vr[i]);
+        return set.ToList();
+      }
+    }
+    [Storable]
+    internal int NumSamples { get; private set; }
+    [Storable]
+    internal bool IsLeaf { get; private set; }
+    [Storable]
+    private IRegressionModel Model { get; set; }
+
+    [Storable]
+    public string SplitAttribute { get; private set; }
+    [Storable]
+    public double SplitValue { get; private set; }
+    [Storable]
+    public RegressionNodeModel Left { get; private set; }
+    [Storable]
+    public RegressionNodeModel Right { get; private set; }
+    [Storable]
+    public RegressionNodeModel Parent { get; private set; }
+    #endregion
+
+    #region HLConstructors
+    [StorableConstructor]
+    protected RegressionNodeModel(StorableConstructorFlag _) : base(_) { }
+    protected RegressionNodeModel(RegressionNodeModel original, Cloner cloner) : base(original, cloner) {
+      IsLeaf = original.IsLeaf;
+      Model = cloner.Clone(original.Model);
+      SplitValue = original.SplitValue;
+      SplitAttribute = original.SplitAttribute;
+      Left = cloner.Clone(original.Left);
+      Right = cloner.Clone(original.Right);
+      Parent = cloner.Clone(original.Parent);
+      NumSamples = original.NumSamples;
+    }
+    private RegressionNodeModel(string targetAttr) : base(targetAttr) {
+      IsLeaf = true;
+    }
+    private RegressionNodeModel(RegressionNodeModel parent) : this(parent.TargetVariable) {
+      Parent = parent;
+      IsLeaf = true;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionNodeModel(this, cloner);
+    }
+    public static RegressionNodeModel CreateNode(string targetAttr, RegressionTreeParameters regressionTreeParams) {
+      return regressionTreeParams.LeafModel.ProvidesConfidence ? new ConfidenceRegressionNodeModel(targetAttr) : new RegressionNodeModel(targetAttr);
+    }
+    private static RegressionNodeModel CreateNode(RegressionNodeModel parent, RegressionTreeParameters regressionTreeParams) {
+      return regressionTreeParams.LeafModel.ProvidesConfidence ? new ConfidenceRegressionNodeModel(parent) : new RegressionNodeModel(parent);
+    }
+    #endregion
+
+    #region RegressionModel
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return Variables; }
+    }
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      if (!IsLeaf) return rows.Select(row => GetEstimatedValue(dataset, row));
+      if (Model == null) throw new NotSupportedException("The model has not been built correctly");
+      return Model.GetEstimatedValues(dataset, rows);
+    }
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+    #endregion
+
+    internal void Split(RegressionTreeParameters regressionTreeParams, string splitAttribute, double splitValue, int numSamples) {
+      NumSamples = numSamples;
+      SplitAttribute = splitAttribute;
+      SplitValue = splitValue;
+      Left = CreateNode(this, regressionTreeParams);
+      Right = CreateNode(this, regressionTreeParams);
+      IsLeaf = false;
+    }
+
+    internal void ToLeaf() {
+      IsLeaf = true;
+      Right = null;
+      Left = null;
+    }
+
+    internal void SetLeafModel(IRegressionModel model) {
+      Model = model;
+    }
+
+    internal IEnumerable<RegressionNodeModel> EnumerateNodes() {
+      var queue = new Queue<RegressionNodeModel>();
+      queue.Enqueue(this);
+      while (queue.Count != 0) {
+        var cur = queue.Dequeue();
+        yield return cur;
+        if (cur.Left == null && cur.Right == null) continue;
+        if (cur.Left != null) queue.Enqueue(cur.Left);
+        if (cur.Right != null) queue.Enqueue(cur.Right);
+      }
+    }
+
+    #region Helpers
+    private double GetEstimatedValue(IDataset dataset, int row) {
+      if (!IsLeaf) return (dataset.GetDoubleValue(SplitAttribute, row) <= SplitValue ? Left : Right).GetEstimatedValue(dataset, row);
+      if (Model == null) throw new NotSupportedException("The model has not been built correctly");
+      return Model.GetEstimatedValues(dataset, new[] {row}).First();
+    }
+    #endregion
+
+    [StorableType("1FF9E216-6AF1-4282-A7EF-3FA0C1DB29C8")]
+    private sealed class ConfidenceRegressionNodeModel : RegressionNodeModel, IConfidenceRegressionModel {
+      #region HLConstructors
+      [StorableConstructor]
+      private ConfidenceRegressionNodeModel(StorableConstructorFlag _) : base(_) { }
+      private ConfidenceRegressionNodeModel(ConfidenceRegressionNodeModel original, Cloner cloner) : base(original, cloner) { }
+      public ConfidenceRegressionNodeModel(string targetAttr) : base(targetAttr) { }
+      public ConfidenceRegressionNodeModel(RegressionNodeModel parent) : base(parent) { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new ConfidenceRegressionNodeModel(this, cloner);
+      }
+      #endregion
+
+      public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+        return IsLeaf ? ((IConfidenceRegressionModel)Model).GetEstimatedVariances(dataset, rows) : rows.Select(row => GetEstimatedVariance(dataset, row));
+      }
+
+      private double GetEstimatedVariance(IDataset dataset, int row) {
+        return !IsLeaf ? ((IConfidenceRegressionModel)(dataset.GetDoubleValue(SplitAttribute, row) <= SplitValue ? Left : Right)).GetEstimatedVariances(dataset, row.ToEnumerable()).Single() : ((IConfidenceRegressionModel)Model).GetEstimatedVariances(dataset, new[] {row}).First();
+      }
+
+      public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+        return new ConfidenceRegressionSolution(this, problemData);
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionNodeTreeModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionNodeTreeModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionNodeTreeModel.cs	(revision 16892)
@@ -0,0 +1,132 @@
+﻿#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("FAF1F955-82F3-4824-9759-9D2846E831AE")]
+  public class RegressionNodeTreeModel : RegressionModel, IM5Model {
+    public const string NumCurrentLeafsResultName = "Number of current leafs";
+    public const string RootVariableName = "Root";
+    #region Properties
+    [Storable]
+    internal RegressionNodeModel Root { get; private set; }
+    #endregion
+
+    #region HLConstructors & Cloning
+    [StorableConstructor]
+    protected RegressionNodeTreeModel(StorableConstructorFlag _) : base(_) { }
+    protected RegressionNodeTreeModel(RegressionNodeTreeModel original, Cloner cloner) : base(original, cloner) {
+      Root = cloner.Clone(original.Root);
+    }
+    protected RegressionNodeTreeModel(string targetVariable) : base(targetVariable) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionNodeTreeModel(this, cloner);
+    }
+    #endregion
+
+    internal static RegressionNodeTreeModel CreateTreeModel(string targetAttr, RegressionTreeParameters regressionTreeParams) {
+      return regressionTreeParams.LeafModel.ProvidesConfidence ? new ConfidenceRegressionNodeTreeModel(targetAttr) : new RegressionNodeTreeModel(targetAttr);
+    }
+
+    #region RegressionModel
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return Root.VariablesUsedForPrediction ?? new List<string>(); }
+    }
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      if (Root == null) throw new NotSupportedException("The model has not been built yet");
+      return Root.GetEstimatedValues(dataset, rows);
+    }
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+    #endregion
+
+    #region IM5Model
+    public void Build(IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope statescope, ResultCollection results, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)statescope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      //start with one node
+      if (Root == null)
+        Root = RegressionNodeModel.CreateNode(regressionTreeParams.TargetVariable, regressionTreeParams);
+
+      //split into (overfitted tree)
+      regressionTreeParams.Splitter.Split(this, trainingRows, statescope, cancellationToken);
+
+      //prune
+      regressionTreeParams.Pruning.Prune(this, trainingRows, pruningRows, statescope, cancellationToken);
+
+      //build final leaf models
+      regressionTreeParams.LeafModel.Build(this, trainingRows.Union(pruningRows).ToArray(), statescope, cancellationToken);
+    }
+
+    public void Update(IReadOnlyList<int> rows, IScope statescope, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)statescope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      regressionTreeParams.LeafModel.Build(this, rows, statescope, cancellationToken);
+    }
+
+    public static void Initialize(IScope stateScope) {
+      var param = (RegressionTreeParameters)stateScope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      stateScope.Variables.Add(new Variable(RootVariableName, RegressionNodeModel.CreateNode(param.TargetVariable, param)));
+    }
+    #endregion
+
+    public void BuildModel(IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope statescope, ResultCollection results, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)statescope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      //start with one node
+      Root = RegressionNodeModel.CreateNode(regressionTreeParams.TargetVariable, regressionTreeParams);
+
+      //split into (overfitted tree)
+      regressionTreeParams.Splitter.Split(this, trainingRows, statescope, cancellationToken);
+
+      //prune
+      regressionTreeParams.Pruning.Prune(this, trainingRows, pruningRows, statescope, cancellationToken);
+    }
+
+    [StorableType("E84ACC40-5694-4E40-A947-190673643206")]
+    private sealed class ConfidenceRegressionNodeTreeModel : RegressionNodeTreeModel, IConfidenceRegressionModel {
+      #region HLConstructors & Cloning
+      [StorableConstructor]
+      private ConfidenceRegressionNodeTreeModel(StorableConstructorFlag _) : base(_) { }
+      private ConfidenceRegressionNodeTreeModel(ConfidenceRegressionNodeTreeModel original, Cloner cloner) : base(original, cloner) { }
+      public ConfidenceRegressionNodeTreeModel(string targetVariable) : base(targetVariable) { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new ConfidenceRegressionNodeTreeModel(this, cloner);
+      }
+      #endregion
+
+      public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+        if (Root == null) throw new NotSupportedException("The model has not been built yet");
+        return ((IConfidenceRegressionModel)Root).GetEstimatedVariances(dataset, rows);
+      }
+      public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+        return new ConfidenceRegressionSolution(this, problemData);
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionRuleModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionRuleModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionRuleModel.cs	(revision 16892)
@@ -0,0 +1,179 @@
+﻿#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;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("425AF262-A756-4E9A-B76F-4D2480BEA4FD")]
+  public class RegressionRuleModel : RegressionModel, IM5Model {
+    #region Properties
+    [Storable]
+    public string[] SplitAttributes { get; set; }
+    [Storable]
+    private double[] SplitValues { get; set; }
+    [Storable]
+    private Comparison[] Comparisons { get; set; }
+    [Storable]
+    private IRegressionModel RuleModel { get; set; }
+    [Storable]
+    private IReadOnlyList<string> variables;
+    #endregion
+
+    #region HLConstructors
+    [StorableConstructor]
+    protected RegressionRuleModel(StorableConstructorFlag _) : base(_) { }
+    protected RegressionRuleModel(RegressionRuleModel original, Cloner cloner) : base(original, cloner) {
+      if (original.SplitAttributes != null) SplitAttributes = original.SplitAttributes.ToArray();
+      if (original.SplitValues != null) SplitValues = original.SplitValues.ToArray();
+      if (original.Comparisons != null) Comparisons = original.Comparisons.ToArray();
+      RuleModel = cloner.Clone(original.RuleModel);
+      if (original.variables != null) variables = original.variables.ToList();
+    }
+    private RegressionRuleModel(string target) : base(target) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionRuleModel(this, cloner);
+    }
+    #endregion
+
+    internal static RegressionRuleModel CreateRuleModel(string target, RegressionTreeParameters regressionTreeParams) {
+      return regressionTreeParams.LeafModel.ProvidesConfidence ? new ConfidenceRegressionRuleModel(target) : new RegressionRuleModel(target);
+    }
+
+    #region IRegressionModel
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return variables; }
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      if (RuleModel == null) throw new NotSupportedException("The model has not been built correctly");
+      return RuleModel.GetEstimatedValues(dataset, rows);
+    }
+
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+    #endregion
+
+    public void Build(IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope statescope, ResultCollection results, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)statescope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      variables = regressionTreeParams.AllowedInputVariables.ToList();
+
+      //build tree and select node with maximum coverage
+      var tree = RegressionNodeTreeModel.CreateTreeModel(regressionTreeParams.TargetVariable, regressionTreeParams);
+      tree.BuildModel(trainingRows, pruningRows, statescope, results, cancellationToken);
+      var nodeModel = tree.Root.EnumerateNodes().Where(x => x.IsLeaf).MaxItems(x => x.NumSamples).First();
+
+      var satts = new List<string>();
+      var svals = new List<double>();
+      var reops = new List<Comparison>();
+
+      //extract splits
+      for (var temp = nodeModel; temp.Parent != null; temp = temp.Parent) {
+        satts.Add(temp.Parent.SplitAttribute);
+        svals.Add(temp.Parent.SplitValue);
+        reops.Add(temp.Parent.Left == temp ? Comparison.LessEqual : Comparison.Greater);
+      }
+      Comparisons = reops.ToArray();
+      SplitAttributes = satts.ToArray();
+      SplitValues = svals.ToArray();
+      int np;
+      RuleModel = regressionTreeParams.LeafModel.BuildModel(trainingRows.Union(pruningRows).Where(r => Covers(regressionTreeParams.Data, r)).ToArray(), regressionTreeParams, cancellationToken, out np);
+    }
+
+    public void Update(IReadOnlyList<int> rows, IScope statescope, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)statescope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      int np;
+      RuleModel = regressionTreeParams.LeafModel.BuildModel(rows, regressionTreeParams, cancellationToken, out np);
+    }
+
+    public bool Covers(IDataset dataset, int row) {
+      return !SplitAttributes.Where((t, i) => !Comparisons[i].Compare(dataset.GetDoubleValue(t, row), SplitValues[i])).Any();
+    }
+
+    public string ToCompactString() {
+      var mins = new Dictionary<string, double>();
+      var maxs = new Dictionary<string, double>();
+      for (var i = 0; i < SplitAttributes.Length; i++) {
+        var n = SplitAttributes[i];
+        var v = SplitValues[i];
+        if (!mins.ContainsKey(n)) mins.Add(n, double.NegativeInfinity);
+        if (!maxs.ContainsKey(n)) maxs.Add(n, double.PositiveInfinity);
+        if (Comparisons[i] == Comparison.LessEqual) maxs[n] = Math.Min(maxs[n], v);
+        else mins[n] = Math.Max(mins[n], v);
+      }
+      if (maxs.Count == 0) return "";
+      var s = new StringBuilder();
+      foreach (var key in maxs.Keys)
+        s.Append(string.Format("{0} ∈ [{1:e2}; {2:e2}] && ", key, mins[key], maxs[key]));
+      s.Remove(s.Length - 4, 4);
+      return s.ToString();
+    }
+
+    [StorableType("7302AA30-9F58-42F3-BF6A-ECF1536508AB")]
+    private sealed class ConfidenceRegressionRuleModel : RegressionRuleModel, IConfidenceRegressionModel {
+      #region HLConstructors
+      [StorableConstructor]
+      private ConfidenceRegressionRuleModel(StorableConstructorFlag _) : base(_) { }
+      private ConfidenceRegressionRuleModel(ConfidenceRegressionRuleModel original, Cloner cloner) : base(original, cloner) { }
+      public ConfidenceRegressionRuleModel(string targetAttr) : base(targetAttr) { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new ConfidenceRegressionRuleModel(this, cloner);
+      }
+      #endregion
+
+      public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+        return ((IConfidenceRegressionModel)RuleModel).GetEstimatedVariances(dataset, rows);
+      }
+
+      public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+        return new ConfidenceRegressionSolution(this, problemData);
+      }
+    }
+  }
+
+  [StorableType("152DECE4-2692-4D53-B290-974806ADCD72")]
+  internal enum Comparison {
+    LessEqual,
+    Greater
+  }
+
+  internal static class ComparisonExtentions {
+    public static bool Compare(this Comparison op, double x, double y) {
+      switch (op) {
+        case Comparison.Greater:
+          return x > y;
+        case Comparison.LessEqual:
+          return x <= y;
+        default:
+          throw new ArgumentOutOfRangeException(op.ToString(), op, null);
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionRuleSetModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionRuleSetModel.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/MetaModels/RegressionRuleSetModel.cs	(revision 16892)
@@ -0,0 +1,186 @@
+﻿#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("7B4D9AE9-0456-4029-80A6-CCB5E33CE356")]
+  public class RegressionRuleSetModel : RegressionModel, IM5Model {
+    private const string NumRulesResultName = "Number of rules";
+    private const string CoveredInstancesResultName = "Covered instances";
+    public const string RuleSetStateVariableName = "RuleSetState";
+
+    #region Properties
+    [Storable]
+    internal List<RegressionRuleModel> Rules { get; private set; }
+    #endregion
+
+    #region HLConstructors & Cloning
+    [StorableConstructor]
+    protected RegressionRuleSetModel(StorableConstructorFlag _) : base(_) { }
+    protected RegressionRuleSetModel(RegressionRuleSetModel original, Cloner cloner) : base(original, cloner) {
+      if (original.Rules != null) Rules = original.Rules.Select(cloner.Clone).ToList();
+    }
+    protected RegressionRuleSetModel(string targetVariable) : base(targetVariable) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionRuleSetModel(this, cloner);
+    }
+    #endregion
+
+    internal static RegressionRuleSetModel CreateRuleModel(string targetAttr, RegressionTreeParameters regressionTreeParams) {
+      return regressionTreeParams.LeafModel.ProvidesConfidence ? new ConfidenceRegressionRuleSetModel(targetAttr) : new RegressionRuleSetModel(targetAttr);
+    }
+
+    #region RegressionModel
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get {
+        var f = Rules.FirstOrDefault();
+        return f != null ? (f.VariablesUsedForPrediction ?? new List<string>()) : new List<string>();
+      }
+    }
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      if (Rules == null) throw new NotSupportedException("The model has not been built yet");
+      return rows.Select(row => GetEstimatedValue(dataset, row));
+    }
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, problemData);
+    }
+    #endregion
+
+    #region IM5Model
+    public void Build(IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope stateScope, ResultCollection results, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)stateScope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      var ruleSetState = (RuleSetState)stateScope.Variables[RuleSetStateVariableName].Value;
+
+      if (ruleSetState.Code <= 0) {
+        ruleSetState.Rules.Clear();
+        ruleSetState.TrainingRows = trainingRows;
+        ruleSetState.PruningRows = pruningRows;
+        ruleSetState.Code = 1;
+      }
+
+      do {
+        var tempRule = RegressionRuleModel.CreateRuleModel(regressionTreeParams.TargetVariable, regressionTreeParams);
+        cancellationToken.ThrowIfCancellationRequested();
+
+        if (!results.ContainsKey(NumRulesResultName)) results.Add(new Result(NumRulesResultName, new IntValue(0)));
+        if (!results.ContainsKey(CoveredInstancesResultName)) results.Add(new Result(CoveredInstancesResultName, new IntValue(0)));
+
+        var t1 = ruleSetState.TrainingRows.Count;
+        tempRule.Build(ruleSetState.TrainingRows, ruleSetState.PruningRows, stateScope, results, cancellationToken);
+        ruleSetState.TrainingRows = ruleSetState.TrainingRows.Where(i => !tempRule.Covers(regressionTreeParams.Data, i)).ToArray();
+        ruleSetState.PruningRows = ruleSetState.PruningRows.Where(i => !tempRule.Covers(regressionTreeParams.Data, i)).ToArray();
+        ruleSetState.Rules.Add(tempRule);
+        ((IntValue)results[NumRulesResultName].Value).Value++;
+        ((IntValue)results[CoveredInstancesResultName].Value).Value += t1 - ruleSetState.TrainingRows.Count;
+      }
+      while (ruleSetState.TrainingRows.Count > 0);
+      Rules = ruleSetState.Rules;
+    }
+    public void Update(IReadOnlyList<int> rows, IScope stateScope, CancellationToken cancellationToken) {
+      foreach (var rule in Rules) rule.Update(rows, stateScope, cancellationToken);
+    }
+    public static void Initialize(IScope stateScope) {
+      stateScope.Variables.Add(new Variable(RuleSetStateVariableName, new RuleSetState()));
+    }
+    #endregion
+
+    #region Helpers
+    private double GetEstimatedValue(IDataset dataset, int row) {
+      foreach (var rule in Rules) {
+        if (rule.Covers(dataset, row))
+          return rule.GetEstimatedValues(dataset, row.ToEnumerable()).Single();
+      }
+      throw new ArgumentException("Instance is not covered by any rule");
+    }
+    #endregion
+
+    [StorableType("E114F3C9-3C1F-443D-8270-0E10CE12F2A0")]
+    public class RuleSetState : Item {
+      [Storable]
+      public List<RegressionRuleModel> Rules = new List<RegressionRuleModel>();
+      [Storable]
+      public IReadOnlyList<int> TrainingRows = new List<int>();
+      [Storable]
+      public IReadOnlyList<int> PruningRows = new List<int>();
+
+      //State.Code values denote the current action (for pausing)
+      //0...nothing has been done;
+      //1...splitting nodes;
+      [Storable]
+      public int Code = 0;
+
+      #region HLConstructors & Cloning
+      [StorableConstructor]
+      protected RuleSetState(StorableConstructorFlag _) : base(_) { }
+      protected RuleSetState(RuleSetState original, Cloner cloner) : base(original, cloner) {
+        Rules = original.Rules.Select(cloner.Clone).ToList();
+        TrainingRows = original.TrainingRows.ToList();
+        PruningRows = original.PruningRows.ToList();
+
+        Code = original.Code;
+      }
+      public RuleSetState() { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new RuleSetState(this, cloner);
+      }
+      #endregion
+    }
+
+    [StorableType("52E7992B-94CC-4960-AA82-1A399BE735C6")]
+    private sealed class ConfidenceRegressionRuleSetModel : RegressionRuleSetModel, IConfidenceRegressionModel {
+      #region HLConstructors & Cloning
+      [StorableConstructor]
+      private ConfidenceRegressionRuleSetModel(StorableConstructorFlag _) : base(_) { }
+      private ConfidenceRegressionRuleSetModel(ConfidenceRegressionRuleSetModel original, Cloner cloner) : base(original, cloner) { }
+      public ConfidenceRegressionRuleSetModel(string targetVariable) : base(targetVariable) { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new ConfidenceRegressionRuleSetModel(this, cloner);
+      }
+      #endregion
+
+      #region IConfidenceRegressionModel
+      public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+        if (Rules == null) throw new NotSupportedException("The model has not been built yet");
+        return rows.Select(row => GetEstimatedVariance(dataset, row));
+      }
+      public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+        return new ConfidenceRegressionSolution(this, problemData);
+      }
+      private double GetEstimatedVariance(IDataset dataset, int row) {
+        foreach (var rule in Rules) {
+          if (rule.Covers(dataset, row)) return ((IConfidenceRegressionModel)rule).GetEstimatedVariances(dataset, row.ToEnumerable()).Single();
+        }
+        throw new ArgumentException("Instance is not covered by any rule");
+      }
+      #endregion
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Plugin.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Plugin.cs.frame	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Plugin.cs.frame	(revision 16892)
@@ -0,0 +1,48 @@
+#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.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Plugin class for HeuristicLab.Algorithms.DataAnalysis plugin.
+  /// </summary>
+  [Plugin("HeuristicLab.Algorithms.DataAnalysis.M5", "Provides the M5' regression algorithm", "3.4.0.$WCREV$")]
+  [PluginFile("HeuristicLab.Algorithms.DataAnalysis.M5-3.4.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.7")]
+  [PluginDependency("HeuristicLab.Attic", "1.0")]
+  [PluginDependency("HeuristicLab.Algorithms.DataAnalysis", "3.4")]
+  [PluginDependency("HeuristicLab.Algorithms.DataAnalysis.Glmnet", "3.4")]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.PermutationEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.4")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")]
+  [PluginDependency("HeuristicLab.Random", "3.3")]
+
+  public class Plugin : PluginBase {   
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Properties/AssemblyInfo.cs.frame	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Properties/AssemblyInfo.cs.frame	(revision 16892)
@@ -0,0 +1,55 @@
+﻿#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.CompilerServices;
+using System.Runtime.InteropServices;
+using HeuristicLab.PluginInfrastructure;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Algorithms.DataAnalysis.M5")]
+[assembly: AssemblyDescription("Provides the M5' regression algorithm")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.4.0")]
+[assembly: AssemblyFileVersion("3.4.0.$WCREV$")]
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Pruning/ComplexityPruning.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Pruning/ComplexityPruning.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Pruning/ComplexityPruning.cs	(revision 16892)
@@ -0,0 +1,325 @@
+﻿#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("B643D965-D13F-415D-8589-3F3527460347")]
+  public class ComplexityPruning : ParameterizedNamedItem, IPruning {
+    public const string PruningStateVariableName = "PruningState";
+
+    public const string PruningStrengthParameterName = "PruningStrength";
+    public const string PruningDecayParameterName = "PruningDecay";
+    public const string FastPruningParameterName = "FastPruning";
+
+    public IFixedValueParameter<DoubleValue> PruningStrengthParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[PruningStrengthParameterName]; }
+    }
+    public IFixedValueParameter<DoubleValue> PruningDecayParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[PruningDecayParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> FastPruningParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[FastPruningParameterName]; }
+    }
+
+    public double PruningStrength {
+      get { return PruningStrengthParameter.Value.Value; }
+      set { PruningStrengthParameter.Value.Value = value; }
+    }
+    public double PruningDecay {
+      get { return PruningDecayParameter.Value.Value; }
+      set { PruningDecayParameter.Value.Value = value; }
+    }
+    public bool FastPruning {
+      get { return FastPruningParameter.Value.Value; }
+      set { FastPruningParameter.Value.Value = value; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected ComplexityPruning(StorableConstructorFlag _) : base(_) { }
+    protected ComplexityPruning(ComplexityPruning original, Cloner cloner) : base(original, cloner) { }
+    public ComplexityPruning() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(PruningStrengthParameterName, "The strength of the pruning. Higher values force the algorithm to create simpler models (default=2.0).", new DoubleValue(2.0)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(PruningDecayParameterName, "Pruning decay allows nodes higher up in the tree to be more stable (default=1.0).", new DoubleValue(1.0)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(FastPruningParameterName, "Accelerate pruning by using linear models instead of leaf models (default=true).", new BoolValue(true)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ComplexityPruning(this, cloner);
+    }
+    #endregion
+
+    #region IPruning
+    public int MinLeafSize(IRegressionProblemData pd, ILeafModel leafModel) {
+      return (FastPruning ? new LinearLeaf() : leafModel).MinLeafSize(pd);
+    }
+    public void Initialize(IScope states) {
+      states.Variables.Add(new Variable(PruningStateVariableName, new PruningState()));
+    }
+
+    public void Prune(RegressionNodeTreeModel treeModel, IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope statescope, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)statescope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      var state = (PruningState)statescope.Variables[PruningStateVariableName].Value;
+
+      var leaf = FastPruning ? new LinearLeaf() : regressionTreeParams.LeafModel;
+      if (state.Code <= 1) {
+        InstallModels(treeModel, state, trainingRows, pruningRows, leaf, regressionTreeParams, cancellationToken);
+        cancellationToken.ThrowIfCancellationRequested();
+      }
+      if (state.Code <= 2) {
+        AssignPruningThresholds(treeModel, state, PruningDecay);
+        cancellationToken.ThrowIfCancellationRequested();
+      }
+      if (state.Code <= 3) {
+        UpdateThreshold(treeModel, state);
+        cancellationToken.ThrowIfCancellationRequested();
+      }
+      if (state.Code <= 4) {
+        Prune(treeModel, state, PruningStrength);
+        cancellationToken.ThrowIfCancellationRequested();
+      }
+
+      state.Code = 5;
+    }
+    #endregion
+
+    private static void InstallModels(RegressionNodeTreeModel tree, PruningState state, IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, ILeafModel leaf, RegressionTreeParameters regressionTreeParams, CancellationToken cancellationToken) {
+      if (state.Code == 0) {
+        state.FillBottomUp(tree, trainingRows, pruningRows, regressionTreeParams.Data);
+        state.Code = 1;
+      }
+      while (state.nodeQueue.Count != 0) {
+        cancellationToken.ThrowIfCancellationRequested();
+        var n = state.nodeQueue.Peek();
+        var training = state.trainingRowsQueue.Peek();
+        var pruning = state.pruningRowsQueue.Peek();
+        BuildPruningModel(n, leaf, training, pruning, state, regressionTreeParams, cancellationToken);
+        state.nodeQueue.Dequeue();
+        state.trainingRowsQueue.Dequeue();
+        state.pruningRowsQueue.Dequeue();
+      }
+    }
+
+    private static void AssignPruningThresholds(RegressionNodeTreeModel tree, PruningState state, double pruningDecay) {
+      if (state.Code == 1) {
+        state.FillBottomUp(tree);
+        state.Code = 2;
+      }
+      while (state.nodeQueue.Count != 0) {
+        var n = state.nodeQueue.Dequeue();
+        if (n.IsLeaf) continue;
+        n.PruningStrength = PruningThreshold(state.pruningSizes[n], state.modelComplexities[n], state.nodeComplexities[n], state.modelErrors[n], SubtreeError(n, state.pruningSizes, state.modelErrors), pruningDecay);
+      }
+    }
+
+    private static void UpdateThreshold(RegressionNodeTreeModel tree, PruningState state) {
+      if (state.Code == 2) {
+        state.FillTopDown(tree);
+        state.Code = 3;
+      }
+      while (state.nodeQueue.Count != 0) {
+        var n = state.nodeQueue.Dequeue();
+        if (n.IsLeaf || n.Parent == null || double.IsNaN(n.Parent.PruningStrength)) continue;
+        n.PruningStrength = Math.Min(n.PruningStrength, n.Parent.PruningStrength);
+      }
+    }
+
+    private static void Prune(RegressionNodeTreeModel tree, PruningState state, double pruningStrength) {
+      if (state.Code == 3) {
+        state.FillTopDown(tree);
+        state.Code = 4;
+      }
+      while (state.nodeQueue.Count != 0) {
+        var n = state.nodeQueue.Dequeue();
+        if (n.IsLeaf || pruningStrength <= n.PruningStrength) continue;
+        n.ToLeaf();
+      }
+    }
+
+    private static void BuildPruningModel(RegressionNodeModel regressionNode, ILeafModel leaf, IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, PruningState state, RegressionTreeParameters regressionTreeParams, CancellationToken cancellationToken) {
+      //create regressionProblemdata from pruning data 
+      var vars = regressionTreeParams.AllowedInputVariables.Concat(new[] { regressionTreeParams.TargetVariable }).ToArray();
+      var reducedData = new Dataset(vars, vars.Select(x => regressionTreeParams.Data.GetDoubleValues(x, pruningRows).ToList()));
+      var pd = new RegressionProblemData(reducedData, regressionTreeParams.AllowedInputVariables, regressionTreeParams.TargetVariable);
+      pd.TrainingPartition.Start = pd.TrainingPartition.End = pd.TestPartition.Start = 0;
+      pd.TestPartition.End = reducedData.Rows;
+
+      //build pruning model
+      int numModelParams;
+      var model = leaf.BuildModel(trainingRows, regressionTreeParams, cancellationToken, out numModelParams);
+
+      //record error and complexities
+      var rmsModel = model.CreateRegressionSolution(pd).TestRootMeanSquaredError;
+      state.pruningSizes.Add(regressionNode, pruningRows.Count);
+      state.modelErrors.Add(regressionNode, rmsModel);
+      state.modelComplexities.Add(regressionNode, numModelParams);
+      if (regressionNode.IsLeaf) { state.nodeComplexities[regressionNode] = state.modelComplexities[regressionNode]; } else { state.nodeComplexities.Add(regressionNode, state.nodeComplexities[regressionNode.Left] + state.nodeComplexities[regressionNode.Right] + 1); }
+    }
+
+    private static double PruningThreshold(double noIntances, double modelParams, double nodeParams, double modelError, double nodeError, double w) {
+      var res = modelError / nodeError;
+      if (modelError.IsAlmost(nodeError)) res = 1.0;
+      res /= Math.Pow((nodeParams + noIntances) / (2 * (modelParams + noIntances)), w);
+      return res;
+    }
+
+    private static double SubtreeError(RegressionNodeModel regressionNode, IDictionary<RegressionNodeModel, int> pruningSizes,
+      IDictionary<RegressionNodeModel, double> modelErrors) {
+      if (regressionNode.IsLeaf) return modelErrors[regressionNode];
+      var errorL = SubtreeError(regressionNode.Left, pruningSizes, modelErrors);
+      var errorR = SubtreeError(regressionNode.Right, pruningSizes, modelErrors);
+      errorL = errorL * errorL * pruningSizes[regressionNode.Left];
+      errorR = errorR * errorR * pruningSizes[regressionNode.Right];
+      return Math.Sqrt((errorR + errorL) / pruningSizes[regressionNode]);
+    }
+
+    [StorableType("EAD60C7E-2C58-45C4-9697-6F735F518CFD")]
+    public class PruningState : Item {
+      [Storable]
+      public IDictionary<RegressionNodeModel, int> modelComplexities = new Dictionary<RegressionNodeModel, int>();
+      [Storable]
+      public IDictionary<RegressionNodeModel, int> nodeComplexities = new Dictionary<RegressionNodeModel, int>();
+      [Storable]
+      public IDictionary<RegressionNodeModel, int> pruningSizes = new Dictionary<RegressionNodeModel, int>();
+      [Storable]
+      public IDictionary<RegressionNodeModel, double> modelErrors = new Dictionary<RegressionNodeModel, double>();
+
+      [Storable]
+      public Queue<RegressionNodeModel> nodeQueue = new Queue<RegressionNodeModel>();
+      [Storable]
+      public Queue<IReadOnlyList<int>> trainingRowsQueue = new Queue<IReadOnlyList<int>>();
+      [Storable]
+      public Queue<IReadOnlyList<int>> pruningRowsQueue = new Queue<IReadOnlyList<int>>();
+
+      //State.Code values denote the current action (for pausing)
+      //0...nothing has been done;
+      //1...building Models;
+      //2...assigning threshold
+      //3...adjusting threshold
+      //4...pruning
+      //5...finished
+      [Storable]
+      public int Code = 0;
+
+      #region HLConstructors & Cloning
+      [StorableConstructor]
+      protected PruningState(StorableConstructorFlag _) : base(_) { }
+      protected PruningState(PruningState original, Cloner cloner) : base(original, cloner) {
+        modelComplexities = original.modelComplexities.ToDictionary(x => cloner.Clone(x.Key), x => x.Value);
+        nodeComplexities = original.nodeComplexities.ToDictionary(x => cloner.Clone(x.Key), x => x.Value);
+        pruningSizes = original.pruningSizes.ToDictionary(x => cloner.Clone(x.Key), x => x.Value);
+        modelErrors = original.modelErrors.ToDictionary(x => cloner.Clone(x.Key), x => x.Value);
+        nodeQueue = new Queue<RegressionNodeModel>(original.nodeQueue.Select(cloner.Clone));
+        trainingRowsQueue = new Queue<IReadOnlyList<int>>(original.trainingRowsQueue.Select(x => (IReadOnlyList<int>)x.ToArray()));
+        pruningRowsQueue = new Queue<IReadOnlyList<int>>(original.pruningRowsQueue.Select(x => (IReadOnlyList<int>)x.ToArray()));
+        Code = original.Code;
+      }
+      public PruningState() { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new PruningState(this, cloner);
+      }
+      #endregion
+
+      public void FillTopDown(RegressionNodeTreeModel tree) {
+        var helperQueue = new Queue<RegressionNodeModel>();
+        nodeQueue.Clear();
+
+        helperQueue.Enqueue(tree.Root);
+        nodeQueue.Enqueue(tree.Root);
+
+        while (helperQueue.Count != 0) {
+          var n = helperQueue.Dequeue();
+          if (n.IsLeaf) continue;
+          helperQueue.Enqueue(n.Left);
+          helperQueue.Enqueue(n.Right);
+          nodeQueue.Enqueue(n.Left);
+          nodeQueue.Enqueue(n.Right);
+        }
+      }
+
+      public void FillTopDown(RegressionNodeTreeModel tree, IReadOnlyList<int> pruningRows, IReadOnlyList<int> trainingRows, IDataset data) {
+        var helperQueue = new Queue<RegressionNodeModel>();
+        var trainingHelperQueue = new Queue<IReadOnlyList<int>>();
+        var pruningHelperQueue = new Queue<IReadOnlyList<int>>();
+        nodeQueue.Clear();
+        trainingRowsQueue.Clear();
+        pruningRowsQueue.Clear();
+
+        helperQueue.Enqueue(tree.Root);
+
+        trainingHelperQueue.Enqueue(trainingRows);
+        pruningHelperQueue.Enqueue(pruningRows);
+
+        nodeQueue.Enqueue(tree.Root);
+        trainingRowsQueue.Enqueue(trainingRows);
+        pruningRowsQueue.Enqueue(pruningRows);
+
+
+        while (helperQueue.Count != 0) {
+          var n = helperQueue.Dequeue();
+          var p = pruningHelperQueue.Dequeue();
+          var t = trainingHelperQueue.Dequeue();
+          if (n.IsLeaf) continue;
+
+          IReadOnlyList<int> leftPruning, rightPruning;
+          RegressionTreeUtilities.SplitRows(p, data, n.SplitAttribute, n.SplitValue, out leftPruning, out rightPruning);
+          IReadOnlyList<int> leftTraining, rightTraining;
+          RegressionTreeUtilities.SplitRows(t, data, n.SplitAttribute, n.SplitValue, out leftTraining, out rightTraining);
+
+          helperQueue.Enqueue(n.Left);
+          helperQueue.Enqueue(n.Right);
+          trainingHelperQueue.Enqueue(leftTraining);
+          trainingHelperQueue.Enqueue(rightTraining);
+          pruningHelperQueue.Enqueue(leftPruning);
+          pruningHelperQueue.Enqueue(rightPruning);
+
+          nodeQueue.Enqueue(n.Left);
+          nodeQueue.Enqueue(n.Right);
+          trainingRowsQueue.Enqueue(leftTraining);
+          trainingRowsQueue.Enqueue(rightTraining);
+          pruningRowsQueue.Enqueue(leftPruning);
+          pruningRowsQueue.Enqueue(rightPruning);
+        }
+      }
+
+      public void FillBottomUp(RegressionNodeTreeModel tree) {
+        FillTopDown(tree);
+        nodeQueue = new Queue<RegressionNodeModel>(nodeQueue.Reverse());
+      }
+
+      public void FillBottomUp(RegressionNodeTreeModel tree, IReadOnlyList<int> pruningRows, IReadOnlyList<int> trainingRows, IDataset data) {
+        FillTopDown(tree, pruningRows, trainingRows, data);
+        nodeQueue = new Queue<RegressionNodeModel>(nodeQueue.Reverse());
+        pruningRowsQueue = new Queue<IReadOnlyList<int>>(pruningRowsQueue.Reverse());
+        trainingRowsQueue = new Queue<IReadOnlyList<int>>(trainingRowsQueue.Reverse());
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Pruning/NoPruning.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Pruning/NoPruning.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Pruning/NoPruning.cs	(revision 16892)
@@ -0,0 +1,51 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("D67152AA-3533-45D2-B77B-4A0742FB4B92")]
+  [Item("NoPruning", "No pruning")]
+  public sealed class NoPruning : ParameterizedNamedItem, IPruning {
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private NoPruning(StorableConstructorFlag _) : base(_) { }
+    private NoPruning(NoPruning original, Cloner cloner) : base(original, cloner) { }
+    public NoPruning() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NoPruning(this, cloner);
+    }
+    #endregion
+
+
+    public int MinLeafSize(IRegressionProblemData pd, ILeafModel leafModel) {
+      return 0;
+    }
+    public void Initialize(IScope states) { }
+
+    public void Prune(RegressionNodeTreeModel treeModel, IReadOnlyList<int> trainingRows, IReadOnlyList<int> pruningRows, IScope scope, CancellationToken cancellationToken) { }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/CorrelationImpurityCalculator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/CorrelationImpurityCalculator.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/CorrelationImpurityCalculator.cs	(revision 16892)
@@ -0,0 +1,88 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Helper class for incremental split calculation.
+  /// Used while moving a potential splitter along the ordered training instances
+  /// </summary>
+  internal class CorreleationImpurityCalculator {
+    #region state
+    //Data
+    private readonly List<double> attributeValues;
+    private readonly List<double> targetValues;
+    private readonly double order;
+    private readonly UnivariateOnlineLR left;
+    private readonly UnivariateOnlineLR right;
+    #endregion
+
+    #region Properties
+    public double Impurity { get; private set; }
+    public double SplitValue {
+      get {
+        if (left.Size <= 0) return double.NegativeInfinity;
+        if (left.Size >= attributeValues.Count) return double.PositiveInfinity;
+        return (attributeValues[left.Size - 1] + attributeValues[left.Size]) / 2;
+      }
+    }
+    public bool ValidPosition {
+      get { return !attributeValues[left.Size - 1].IsAlmost(attributeValues[left.Size]); }
+    }
+    public int LeftSize {
+      get { return left.Size; }
+    }
+    #endregion
+
+    #region Constructors
+    public CorreleationImpurityCalculator(int partition, IEnumerable<double> atts, IEnumerable<double> targets, double order) {
+      if (order <= 0) throw new ArgumentException("Splitter order must be larger than 0");
+      this.order = order;
+      attributeValues = atts.ToList();
+      targetValues = targets.ToList();
+      left = new UnivariateOnlineLR(attributeValues.Take(partition).ToList(), targetValues.Take(partition).ToList());
+      right = new UnivariateOnlineLR(attributeValues.Skip(partition).ToList(), targetValues.Skip(partition).ToList());
+      UpdateImpurity();
+    }
+    #endregion
+
+    #region IImpurityCalculator
+    public void Increment() {
+      var target = targetValues[left.Size];
+      var att = attributeValues[left.Size];
+      left.Add(att, target);
+      right.Remove(att, target);
+      UpdateImpurity();
+    }
+    #endregion
+
+    private void UpdateImpurity() {
+      var yl = Math.Pow(left.Ssr, 1.0 / order);
+      var yr = Math.Pow(right.Ssr, 1.0 / order);
+      if (left.Size > 1 && right.Size > 1) Impurity = -yl - yr;
+      else Impurity = double.MinValue;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/CorrelationSplitter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/CorrelationSplitter.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/CorrelationSplitter.cs	(revision 16892)
@@ -0,0 +1,98 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("EC3A5009-EE84-4E1A-A537-20F6F1224842")]
+  [Item("CorrelationSplitter", "An experimental split selector that uses correlation coefficients")]
+  public sealed class CorrelationSplitter : SplitterBase {
+    public const string OrderParameterName = "Order";
+    public IFixedValueParameter<DoubleValue> OrderParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[OrderParameterName]; }
+    }
+    public double Order {
+      get { return OrderParameter.Value.Value; }
+      set { OrderParameter.Value.Value = value; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private CorrelationSplitter(StorableConstructorFlag _) { }
+    private CorrelationSplitter(CorrelationSplitter original, Cloner cloner) : base(original, cloner) { }
+    public CorrelationSplitter() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(OrderParameterName, "The exponent in the split calculation ssrLeft^(1/Order)+ssrRight^(1/Order) (default=1.0).", new DoubleValue(1)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CorrelationSplitter(this, cloner);
+    }
+    #endregion
+
+    #region ISplitType
+    protected override void AttributeSplit(IReadOnlyList<double> attValues, IReadOnlyList<double> targetValues, int minLeafSize, out int leftSize, out double maxImpurity, out double splitValue) {
+      leftSize = -1;
+      splitValue = double.MinValue;
+      maxImpurity = double.NegativeInfinity;
+      var splitValues = new List<double>();
+      var splitSizes = new List<int>();
+      var length = attValues.Count;
+
+      var start = minLeafSize;
+      while (start < length && attValues[start - 1].IsAlmost(attValues[start]))
+        start++;
+      if (start >= length) return;
+
+      var imp = new CorreleationImpurityCalculator(minLeafSize, attValues, targetValues, Order);
+      maxImpurity = imp.Impurity;
+      splitValues.Add(imp.SplitValue);
+      splitSizes.Add(imp.LeftSize);
+
+      while (imp.LeftSize < length - minLeafSize) {
+        imp.Increment();
+        if (!imp.ValidPosition) continue; //splits can not be made between to equal points
+
+        if (imp.Impurity.IsAlmost(maxImpurity)) {
+          splitValues.Add(imp.SplitValue);
+          splitSizes.Add(imp.LeftSize);
+          continue;
+        }
+
+        if (imp.Impurity < maxImpurity) continue;
+        splitValues.Clear();
+        splitSizes.Clear();
+        maxImpurity = imp.Impurity;
+        splitValues.Add(imp.SplitValue);
+        splitSizes.Add(imp.LeftSize);
+      }
+
+      var j = splitSizes.Count / 2;
+      if (splitSizes.Count == 0) return;
+      splitValue = splitValues[j];
+      leftSize = splitSizes[j];
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/M5Splitter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/M5Splitter.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/M5Splitter.cs	(revision 16892)
@@ -0,0 +1,80 @@
+﻿#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.Data;
+using HeuristicLab.Parameters;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("502B1429-7A28-45C1-A60A-93E72CB3AF4A")]
+  [Item("M5Splitter", "A split selector that uses the ratio between Variances^(1/Order) to determine good splits.")]
+  public sealed class M5Splitter : SplitterBase {
+    public const string OrderParameterName = "Order";
+    public IFixedValueParameter<DoubleValue> OrderParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[OrderParameterName]; }
+    }
+    public double Order {
+      get { return OrderParameter.Value.Value; }
+      set { OrderParameter.Value.Value = value; }
+    }
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private M5Splitter(StorableConstructorFlag _) { }
+    private M5Splitter(M5Splitter original, Cloner cloner) : base(original, cloner) { }
+    public M5Splitter() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(OrderParameterName, "The exponent in the split calculation sum (x_i - x_avg)^Order (default=5).", new DoubleValue(5)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new M5Splitter(this, cloner);
+    }
+    #endregion
+
+    protected override void AttributeSplit(IReadOnlyList<double> attValues, IReadOnlyList<double> targetValues, int minLeafSize, out int position, out double maxImpurity, out double splitValue) {
+      position = 0;
+      maxImpurity = double.NegativeInfinity;
+      splitValue = 0.0;
+      var length = targetValues.Count;
+
+      // weka code
+      var low = 0;
+      var high = length - 1;
+      if (high - low + 1 < 4) return;
+      var len = Math.Max(minLeafSize - 1, high - low + 1 < 5 ? 1 : (high - low + 1) / 5);
+      position = low;
+      var part = low + len - 1;
+      var imp = new OrderImpurityCalculator(part + 1, targetValues, Order);
+
+      for (var i = low + len; i < high - len; i++) {
+        imp.Increment(targetValues[i], OrderImpurityCalculator.IncrementType.Left);
+        if (attValues[i].IsAlmost(attValues[i + 1])) continue; //splits can not be made between to equal points
+        if (imp.Impurity < maxImpurity) continue;
+        maxImpurity = imp.Impurity;
+        splitValue = (attValues[i] + attValues[i + 1]) / 2;
+        position = i;
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/NeumaierSum.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/NeumaierSum.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/NeumaierSum.cs	(revision 16892)
@@ -0,0 +1,63 @@
+﻿#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.Runtime.CompilerServices;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Helper class for incremental split calculation.
+  /// Used while moving a potential Splitter along the ordered training Instances
+  /// </summary>
+  internal class NeumaierSum {
+    #region state
+    private double sum;
+    private double correction;
+    #endregion
+
+    #region Constructors
+    public NeumaierSum(double startvalue) {
+      sum = startvalue;
+      correction = 0;
+    }
+    #endregion
+
+    [MethodImpl(MethodImplOptions.NoOptimization)]
+    public void Add(double value) {
+      var t = sum + value;
+      var absSum = sum > 0 ? sum : -sum;
+      var absv = value > 0 ? value : -value;
+      if (absSum >= absv)
+        correction += (sum - t) + value;
+      else
+        correction += (value - t) + sum;
+      sum = t;
+    }
+
+    public double Get() {
+      return sum + correction;
+    }
+
+    public void Mul(double value) {
+      sum *= value;
+      correction *= value;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/OrderImpurityCalculator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/OrderImpurityCalculator.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/OrderImpurityCalculator.cs	(revision 16892)
@@ -0,0 +1,123 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Helper class for incremental split calculation.
+  /// Used while moving a potential splitter along the ordered training instances
+  /// </summary>
+  internal class OrderImpurityCalculator {
+    internal enum IncrementType {
+      Left,
+      Right,
+      None
+    }
+
+    #region Properties
+    private double SqSumLeft { get; set; }
+    private double SqSumRight { get; set; }
+    private double VarLeft { get; set; }
+    private double VarRight { get; set; }
+    private double Order { get; set; }
+    private double VarTotal { get; set; }
+    private int NoInstances { get; set; }
+
+    private double NoLeft { get; set; }
+    private double NoRight { get; set; }
+    private double SumLeft { get; set; }
+    private double SumRight { get; set; }
+    public double Impurity { get; private set; }
+    #endregion
+
+    #region Constructors
+    public OrderImpurityCalculator(int partition, IReadOnlyCollection<double> data, double order) {
+      var values = data;
+      NoInstances = data.Count;
+      VarTotal = values.VariancePop();
+
+      values = data.Take(partition).ToArray();
+      NoLeft = partition;
+      SumLeft = values.Sum();
+      SqSumLeft = values.Sum(x => x * x);
+
+      values = data.Skip(partition).ToArray();
+      NoRight = NoInstances - NoLeft;
+      SumRight = values.Sum();
+      SqSumRight = values.Sum(x => x * x);
+
+      Order = order;
+      Increment(0.0, IncrementType.None);
+    }
+    #endregion
+
+    #region IImpurityCalculator
+    public void Increment(double value, IncrementType type) {
+      double y, yl, yr;
+      var valSq = value * value;
+
+      switch (type) {
+        case IncrementType.Left:
+          NoLeft++;
+          NoRight--;
+          SumLeft += value;
+          SumRight -= value;
+          SqSumLeft += valSq;
+          SqSumRight -= valSq;
+          break;
+        case IncrementType.Right:
+          NoLeft--;
+          NoRight++;
+          SumLeft -= value;
+          SumRight += value;
+          SqSumLeft -= valSq;
+          SqSumRight += valSq;
+          break;
+        case IncrementType.None:
+          break;
+        default:
+          throw new ArgumentOutOfRangeException(type.ToString(), type, null);
+      }
+
+      VarLeft = NoLeft <= 0 ? 0 : Math.Abs(NoLeft * SqSumLeft - SumLeft * SumLeft) / (NoLeft * NoLeft);
+      VarRight = NoRight <= 0 ? 0 : Math.Abs(NoRight * SqSumRight - SumRight * SumRight) / (NoRight * NoRight);
+
+      if (Order <= 0) throw new ArgumentException("Splitter order must be larger than 0");
+      if (Order.IsAlmost(1)) {
+        y = VarTotal;
+        yl = VarLeft;
+        yr = VarRight;
+      }
+      else {
+        y = Math.Pow(VarTotal, 1.0 / Order);
+        yl = Math.Pow(VarLeft, 1.0 / Order);
+        yr = Math.Pow(VarRight, 1.0 / Order);
+      }
+      if (NoLeft <= 0.0 || NoRight <= 0.0) Impurity = double.MinValue; //Splitter = 0;
+      else Impurity = y - (NoLeft * yl + NoRight * yr) / (NoRight + NoLeft);
+    }
+    #endregion
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/SplitterBase.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/SplitterBase.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/SplitterBase.cs	(revision 16892)
@@ -0,0 +1,140 @@
+﻿#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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+using HEAL.Attic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableType("22DCCF28-8943-4622-BBD3-B2AB04F28C36")]
+  [Item("SplitterBase", "Abstract base class for splitters")]
+  public abstract class SplitterBase : ParameterizedNamedItem, ISplitter {
+    public const string SplittingStateVariableName = "SplittingState";
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    protected SplitterBase(StorableConstructorFlag _) { }
+    protected SplitterBase(SplitterBase original, Cloner cloner) : base(original, cloner) { }
+    public SplitterBase() { }
+    #endregion
+
+    #region ISplitType
+    public void Initialize(IScope states) {
+      states.Variables.Add(new Variable(SplittingStateVariableName, new SplittingState()));
+    }
+
+    public void Split(RegressionNodeTreeModel tree, IReadOnlyList<int> trainingRows, IScope stateScope, CancellationToken cancellationToken) {
+      var regressionTreeParams = (RegressionTreeParameters)stateScope.Variables[M5Regression.RegressionTreeParameterVariableName].Value;
+      var splittingState = (SplittingState)stateScope.Variables[SplittingStateVariableName].Value;
+      var variables = regressionTreeParams.AllowedInputVariables.ToArray();
+      var target = regressionTreeParams.TargetVariable;
+
+      if (splittingState.Code <= 0) {
+        splittingState.nodeQueue.Enqueue(tree.Root);
+        splittingState.trainingRowsQueue.Enqueue(trainingRows);
+        splittingState.Code = 1;
+      }
+      while (splittingState.nodeQueue.Count != 0) {
+        var n = splittingState.nodeQueue.Dequeue();
+        var rows = splittingState.trainingRowsQueue.Dequeue();
+
+        string attr;
+        double splitValue;
+        var isLeaf = !DecideSplit(new RegressionProblemData(RegressionTreeUtilities.ReduceDataset(regressionTreeParams.Data, rows, variables, target), variables, target), regressionTreeParams.MinLeafSize, out attr, out splitValue);
+        if (isLeaf) continue;
+
+        IReadOnlyList<int> leftRows, rightRows;
+        RegressionTreeUtilities.SplitRows(rows, regressionTreeParams.Data, attr, splitValue, out leftRows, out rightRows);
+        n.Split(regressionTreeParams, attr, splitValue, rows.Count);
+
+        splittingState.nodeQueue.Enqueue(n.Left);
+        splittingState.nodeQueue.Enqueue(n.Right);
+        splittingState.trainingRowsQueue.Enqueue(leftRows);
+        splittingState.trainingRowsQueue.Enqueue(rightRows);
+        cancellationToken.ThrowIfCancellationRequested();
+      }
+    }
+
+    protected virtual bool DecideSplit(IRegressionProblemData splitData, int minLeafSize, out string splitAttr, out double splitValue) {
+      var bestPos = -1;
+      var bestImpurity = double.MinValue;
+      var bestSplitValue = 0.0;
+      var bestSplitAttr = string.Empty;
+      splitAttr = bestSplitAttr;
+      splitValue = bestSplitValue;
+      if (splitData.Dataset.Rows < minLeafSize) return false;
+
+      // find best attribute for the splitter
+      foreach (var attr in splitData.AllowedInputVariables) {
+        int pos;
+        double impurity, sValue;
+        var sortedData = splitData.Dataset.GetDoubleValues(attr).Zip(splitData.Dataset.GetDoubleValues(splitData.TargetVariable), Tuple.Create).OrderBy(x => x.Item1).ToArray();
+        AttributeSplit(sortedData.Select(x => x.Item1).ToArray(), sortedData.Select(x => x.Item2).ToArray(), minLeafSize, out pos, out impurity, out sValue);
+        if (!(bestImpurity < impurity)) continue;
+        bestImpurity = impurity;
+        bestPos = pos;
+        bestSplitValue = sValue;
+        bestSplitAttr = attr;
+      }
+
+      splitAttr = bestSplitAttr;
+      splitValue = bestSplitValue;
+      //if no suitable split exists => leafNode
+      return bestPos + 1 >= minLeafSize && bestPos <= splitData.Dataset.Rows - minLeafSize;
+    }
+
+    protected abstract void AttributeSplit(IReadOnlyList<double> attValues, IReadOnlyList<double> targetValues, int minLeafSize, out int position, out double maxImpurity, out double splitValue);
+    #endregion
+
+    [StorableType("BC1149FD-370E-4F3A-92F5-6E519736D09A")]
+    public class SplittingState : Item {
+      [Storable]
+      public Queue<RegressionNodeModel> nodeQueue = new Queue<RegressionNodeModel>();
+      [Storable]
+      public Queue<IReadOnlyList<int>> trainingRowsQueue = new Queue<IReadOnlyList<int>>();
+
+      //State.Code values denote the current action (for pausing)
+      //0...nothing has been done;
+      //1...splitting nodes;
+      [Storable]
+      public int Code = 0;
+
+      #region HLConstructors & Cloning
+      [StorableConstructor]
+      protected SplittingState(StorableConstructorFlag _) : base(_) { }
+      protected SplittingState(SplittingState original, Cloner cloner) : base(original, cloner) {
+        nodeQueue = new Queue<RegressionNodeModel>(original.nodeQueue.Select(cloner.Clone));
+        trainingRowsQueue = new Queue<IReadOnlyList<int>>(original.trainingRowsQueue.Select(x => (IReadOnlyList<int>)x.ToArray()));
+        Code = original.Code;
+      }
+      public SplittingState() { }
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new SplittingState(this, cloner);
+      }
+      #endregion
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/UnivariateOnlineLR.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/UnivariateOnlineLR.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis.M5/3.4/Splitting/UnivariateOnlineLR.cs	(revision 16892)
@@ -0,0 +1,114 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Helper class for incremental split calculation.
+  /// Used while moving a potential splitter along the ordered training instances
+  /// </summary>
+  internal class UnivariateOnlineLR {
+    #region state
+    private readonly NeumaierSum targetMean;
+    private readonly NeumaierSum attributeMean;
+    private readonly NeumaierSum targetVarSum;
+    private readonly NeumaierSum attributeVarSum;
+    private readonly NeumaierSum comoment;
+    private readonly NeumaierSum ssr;
+    private int size;
+    #endregion
+
+    public double Ssr {
+      get { return ssr.Get(); }
+    }
+    public int Size {
+      get { return size; }
+    }
+
+    private double Beta {
+      get { return comoment.Get() / attributeVarSum.Get(); }
+    }
+    private double Alpha {
+      get { return targetMean.Get() - Beta * attributeMean.Get(); }
+    }
+
+    public UnivariateOnlineLR(ICollection<double> attributeValues, ICollection<double> targetValues) {
+      if (attributeValues.Count != targetValues.Count) throw new ArgumentException("Targets and Attributes need to have the same length");
+      size = attributeValues.Count;
+
+      var yMean = targetValues.Average();
+      var xMean = attributeValues.Average();
+      targetMean = new NeumaierSum(yMean);
+      attributeMean = new NeumaierSum(xMean);
+      targetVarSum = new NeumaierSum(targetValues.VariancePop() * size);
+      attributeVarSum = new NeumaierSum(attributeValues.VariancePop() * size);
+      comoment = new NeumaierSum(attributeValues.Zip(targetValues, (x, y) => (x - xMean) * (y - yMean)).Sum());
+
+      var beta = comoment.Get() / attributeVarSum.Get();
+      var alpha = yMean - beta * xMean;
+      ssr = new NeumaierSum(attributeValues.Zip(targetValues, (x, y) => y - alpha - beta * x).Sum(x => x * x));
+    }
+
+    public void Add(double attributeValue, double targetValue) {
+      var predictOld = Predict(attributeValue, targetValue);
+
+      size++;
+      var dx = attributeValue - attributeMean.Get();
+      var dy = targetValue - targetMean.Get();
+      attributeMean.Add(dx / size);
+      targetMean.Add(dy / size);
+      var dx2 = attributeValue - attributeMean.Get();
+      var dy2 = targetValue - targetMean.Get();
+      attributeVarSum.Add(dx * dx2);
+      targetVarSum.Add(dy * dy2);
+      comoment.Add(dx * dy2);
+
+      ssr.Add(predictOld * Predict(attributeValue, targetValue));
+    }
+
+    public void Remove(double attributeValue, double targetValue) {
+      var predictOld = Predict(attributeValue, targetValue);
+
+      var dx2 = attributeValue - attributeMean.Get();
+      var dy2 = targetValue - targetMean.Get();
+      attributeMean.Mul(size / (size - 1.0));
+      targetMean.Mul(size / (size - 1.0));
+      attributeMean.Add(-attributeValue / (size - 1.0));
+      targetMean.Add(-targetValue / (size - 1.0));
+      var dx = attributeValue - attributeMean.Get();
+      var dy = targetValue - targetMean.Get();
+      attributeVarSum.Add(-dx * dx2);
+      targetVarSum.Add(-dy * dy2);
+      comoment.Add(-dx * dy2);
+      size--;
+
+      ssr.Add(-predictOld * Predict(attributeValue, targetValue));
+    }
+
+    private double Predict(double attributeValue, double targetValue) {
+      return targetValue - Alpha - Beta * attributeValue;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs	(revision 16892)
@@ -300,5 +300,5 @@
         if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
           throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
-        seed = new FastRandom().NextInt();
+        seed = RandomSeedGenerator.GetSeed();
 
         if (Algorithm == null) return;
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/GradientBoostedTrees/RegressionTreeModel.cs	(revision 16892)
@@ -91,5 +91,5 @@
     #region old storable format
     // remove with HL 3.4
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "SerializedTree")]
     // to prevent storing the references to data caches in nodes
     // seemingly, it is bad (performance-wise) to persist tuples (tuples are used as keys in a dictionary)
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 16892)
@@ -294,5 +294,5 @@
         return IsProblemDataCompatible(classificationProblemData, out errorMessage);
 
-      throw new ArgumentException("The problem data is not a regression nor a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      throw new ArgumentException("The problem data is not compatible with this nearest neighbour model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 16892)
@@ -144,5 +144,5 @@
         return IsProblemDataCompatible(classificationProblemData, out errorMessage);
 
-      throw new ArgumentException("The problem data is not a regression nor a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      throw new ArgumentException("The problem data is not compatible with this neural network ensemble. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
     }
 
@@ -153,5 +153,5 @@
       return new NeuralNetworkEnsembleClassificationSolution(this, new ClassificationEnsembleProblemData(problemData));
     }
-   
+
     #region persistence
     [Storable]
@@ -183,5 +183,5 @@
       }
     }
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "MultiLayerPerceptronEnsembleDfdnet")]
     private double[] MultiLayerPerceptronEnsembleDfdnet {
       set {
@@ -197,9 +197,9 @@
       }
     }
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "MultiLayerPerceptronEnsembleNeurons")]
     private double[] MultiLayerPerceptronEnsembleNeurons {
       set { mlpEnsemble.innerobj.network.neurons = value; }
     }
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "MultiLayerPerceptronEnsembleSerializedMlp")]
     private double[] MultiLayerPerceptronEnsembleSerializedMlp {
       set {
@@ -207,5 +207,5 @@
       }
     }
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "MultiLayerPerceptronStuctinfo")]
     private int[] MultiLayerPerceptronStuctinfo {
       set {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 16892)
@@ -147,5 +147,5 @@
         return IsProblemDataCompatible(classificationProblemData, out errorMessage);
 
-      throw new ArgumentException("The problem data is not a regression nor a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      throw new ArgumentException("The problem data is not compatible with this neural network. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 16892)
@@ -300,5 +300,5 @@
         return IsProblemDataCompatible(classificationProblemData, out errorMessage);
 
-      throw new ArgumentException("The problem data is not a regression nor a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      throw new ArgumentException("The problem data is not compatible with this random forest. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.DataAnalysis/3.4/SupportVectorMachine/SupportVectorMachineModel.cs	(revision 16892)
@@ -143,5 +143,5 @@
         return IsProblemDataCompatible(classificationProblemData, out errorMessage);
 
-      throw new ArgumentException("The problem data is not a regression nor a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      throw new ArgumentException("The problem data is not compatible with this SVM. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.GeneticAlgorithm/3.3/IslandGeneticAlgorithm.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.GeneticAlgorithm/3.3/IslandGeneticAlgorithm.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.GeneticAlgorithm/3.3/IslandGeneticAlgorithm.cs	(revision 16892)
@@ -22,4 +22,5 @@
 using System;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
@@ -30,5 +31,4 @@
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.PluginInfrastructure;
 using HeuristicLab.Random;
@@ -372,6 +372,6 @@
     protected override void OnProblemChanged() {
       ParameterizeStochasticOperator(Problem.SolutionCreator);
+      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
       ParameterizeStochasticOperatorForIsland(Problem.Evaluator);
-      foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
       ParameterizeSolutionsCreator();
       ParameterizeMainLoop();
@@ -402,4 +402,5 @@
     protected override void Problem_OperatorsChanged(object sender, EventArgs e) {
       foreach (IOperator op in Problem.Operators.OfType<IOperator>()) ParameterizeStochasticOperator(op);
+      ParameterizeStochasticOperatorForIsland(Problem.Evaluator);
       ParameterizeIterationBasedOperators();
       UpdateCrossovers();
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.OffspringSelectionGeneticAlgorithm/3.3/OffspringSelectionGeneticAlgorithmMainOperator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.OffspringSelectionGeneticAlgorithm/3.3/OffspringSelectionGeneticAlgorithmMainOperator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Algorithms.OffspringSelectionGeneticAlgorithm/3.3/OffspringSelectionGeneticAlgorithmMainOperator.cs	(revision 16892)
@@ -20,4 +20,5 @@
 #endregion
 
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -26,5 +27,4 @@
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.Selection;
 
@@ -218,8 +218,8 @@
 
       variableCreator1.Name = "MutatedOffspring = true";
-      variableCreator1.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(true), false));
+      variableCreator1.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(true)) { GetsCollected = false });
 
       variableCreator2.Name = "MutatedOffspring = false";
-      variableCreator2.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(false), false));
+      variableCreator2.CollectedValues.Add(new ValueParameter<BoolValue>("MutatedOffspring", null, new BoolValue(false)) { GetsCollected = false });
 
       conditionalSelector.ConditionParameter.ActualName = "MutatedOffspring";
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 16892)
@@ -227,9 +227,9 @@
     internal DataRowHistogramAggregation? Aggregation { get; private set; }
 
-    [Storable(Name = "Bins", AllowOneWay = true)]
+    [Storable(OldName = "Bins")]
     private int StorableBins { set { Bins = value; } }
-    [Storable(Name = "ExactBins", AllowOneWay = true)]
+    [Storable(OldName = "ExactBins")]
     private bool StorableExactBins { set { ExactBins = value; } }
-    [Storable(Name = "Aggregation", AllowOneWay = true)]
+    [Storable(OldName = "Aggregation")]
     private DataRowHistogramAggregation StorableAggregation { set { Aggregation = value; } }
     #endregion
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/DataTableValuesCollector.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/DataTableValuesCollector.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/DataTableValuesCollector.cs	(revision 16892)
@@ -22,4 +22,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -27,5 +28,4 @@
 using HeuristicLab.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Analysis {
@@ -59,5 +59,5 @@
       : base() {
       Parameters.Add(new ValueLookupParameter<DataTable>("DataTable", "The table of data values where the collected values should be stored."));
-      Parameters.Add(new FixedValueParameter<BoolValue>("StartIndexZero", "True, if the collected data values should start with index 0, otherwise false.", new BoolValue(true), false));
+      Parameters.Add(new FixedValueParameter<BoolValue>("StartIndexZero", "True, if the collected data values should start with index 0, otherwise false.", new BoolValue(true)) { GetsCollected = false });
       StartIndexZeroParameter.Hidden = true;
     }
@@ -68,5 +68,5 @@
       #region Backwards compatible code (remove with 3.4)
       if (!Parameters.ContainsKey("StartIndexZero")) {
-        Parameters.Add(new FixedValueParameter<BoolValue>("StartIndexZero", "True, if the collected data values should start with index 0, otherwise false.", new BoolValue(true), false));
+        Parameters.Add(new FixedValueParameter<BoolValue>("StartIndexZero", "True, if the collected data values should start with index 0, otherwise false.", new BoolValue(true)) { GetsCollected = false });
         StartIndexZeroParameter.Hidden = true;
       }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataRow.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataRow.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/IndexedDataRow.cs	(revision 16892)
@@ -61,5 +61,5 @@
     #region Backwards compatible code, remove with 3.4
     // tuples are stored inefficiently
-    [Storable(Name = "values", AllowOneWay = true)]
+    [Storable(OldName = "values")]
     private IEnumerable<Tuple<T, double>> StorableValues {
       set { values = new ObservableList<Tuple<T, double>>(value); }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs	(revision 16892)
@@ -107,15 +107,15 @@
     #region Backwards compatible code, remove with 3.4
     private ObservableList<PointF> points;
-    [Storable(Name = "points", AllowOneWay = true)]
+    [Storable(OldName = "points")]
     private ObservableList<PointF> StorablePoints {
       set { points = value; }
     }
     private string xAxisName;
-    [Storable(Name = "xAxisName", AllowOneWay = true)]
+    [Storable(OldName = "xAxisName")]
     private string StorableXAxisName {
       set { xAxisName = value; }
     }
     private string yAxisName;
-    [Storable(Name = "yAxisName", AllowOneWay = true)]
+    [Storable(OldName = "yAxisName")]
     private string StorableYAxisName {
       set { yAxisName = value; }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Analysis/3.3/PopulationSimilarityAnalysis/PopulationSimilarityAnalyzer.cs	(revision 16892)
@@ -44,5 +44,5 @@
     #region Backwards compatible code, remove with 3.4
     private ISolutionSimilarityCalculator oldSimilarityCalculator;
-    [Storable(AllowOneWay = true, Name = "SimilarityCalculator")]
+    [Storable(OldName = "SimilarityCalculator")]
     [Obsolete]
     private ISolutionSimilarityCalculator SimilarityCalculator { set { oldSimilarityCalculator = value; } }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs	(revision 16892)
@@ -26,10 +26,10 @@
 using System.Threading.Tasks;
 using System.Windows.Forms;
+using HeuristicLab.Clients.Hive.Views;
+using HeuristicLab.Core;
+using HeuristicLab.Core.Views;
+using HeuristicLab.Data;
 using HeuristicLab.MainForm;
 using HeuristicLab.MainForm.WindowsForms;
-using HeuristicLab.Core.Views;
-using HeuristicLab.Data;
-using HeuristicLab.Clients.Hive.Views;
-using HeuristicLab.Core;
 
 namespace HeuristicLab.Clients.Hive.Administrator.Views {
@@ -297,5 +297,5 @@
 
     private void RefreshJobs() {
-      HiveAdminClient.Instance.RefreshJobs();
+      HiveAdminClient.Instance.RefreshJobs(Content.Id);
       UpdateJobs();
       SetEnabledStateOfControls();
@@ -303,5 +303,5 @@
 
     private StringMatrix CreateValueMatrix() {
-      if (Content == null || Content.Id == Guid.Empty)
+      if (Content == null || Content.Id == Guid.Empty || !HiveAdminClient.Instance.Jobs.ContainsKey(Content.Id))
         return new StringMatrix();
 
@@ -352,6 +352,4 @@
 
             matrixView.DataGridView.AutoResizeColumns();
-            matrixView.DataGridView.Columns[0].MinimumWidth = 90;
-            matrixView.DataGridView.Columns[1].MinimumWidth = 108;
           }
         }
@@ -360,5 +358,5 @@
 
     private void RefreshJobsAsync() {
-      HiveAdminClient.Instance.RefreshJobs();
+      HiveAdminClient.Instance.RefreshJobs(Content.Id);
       UpdateJobs();
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 16892)
@@ -21,10 +21,10 @@
 
 using System;
+using System.Collections.Generic;
+using System.Linq;
 using System.Threading;
+using HeuristicLab.Clients.Access;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Clients.Access;
 
 namespace HeuristicLab.Clients.Hive {
@@ -77,5 +77,5 @@
         if (value != jobs)
           jobs = value;
-        }
+      }
     }
 
@@ -166,15 +166,8 @@
           if (projectIds.Any()) {
             service.GetAssignedResourcesForProjectsAdministration(projectIds)
-              .ForEach(a => projectResourceAssignments.Add(a));
-            projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<RefreshableJob>()));
+                   .ForEach(a => projectResourceAssignments.Add(a));
+
             var unsortedJobs = service.GetJobsByProjectIds(projectIds)
-              .OrderBy(x => x.DateCreated).ToList();
-
-            unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
-            unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
-            unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
-
-            foreach (var job in jobs.SelectMany(x => x.Value))
-              LoadLightweightJob(job);
+                                      .OrderBy(x => x.DateCreated).ToList();
 
             projectNames = service.GetProjectNames();
@@ -187,60 +180,10 @@
         RefreshDisabledParentProjects();
         RefreshDisabledParentResources();
-      }
-      catch {
+      } catch {
         throw;
-      }
-      finally {
+      } finally {
         OnRefreshed();
       }
     }
-
-    //public void UpdateResourceGenealogy(IItemList<Resource> resources) {
-    //  resourceAncestors.Clear();
-    //  resourceDescendants.Clear();
-
-    //  foreach (var r in resources) {
-    //    resourceAncestors.Add(r.Id, new HashSet<Resource>());
-    //    resourceDescendants.Add(r.Id, new HashSet<Resource>());
-    //  }
-
-    //  foreach (var r in resources) {
-    //    var parentResourceId = r.ParentResourceId;
-    //    while (parentResourceId != null) {
-    //      var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
-    //      if (parent != null) {
-    //        resourceAncestors[r.Id].Add(parent);
-    //        resourceDescendants[parent.Id].Add(r);
-    //        parentResourceId = parent.ParentResourceId;
-    //      } else {
-    //        parentResourceId = null;
-    //      }
-    //    }
-    //  }
-    //}
-
-    //public void UpdateProjectGenealogy(IItemList<Project> projects) {
-    //  projectAncestors.Clear();
-    //  projectDescendants.Clear();
-
-    //  foreach (var p in projects) {
-    //    projectAncestors.Add(p.Id, new HashSet<Project>());
-    //    projectDescendants.Add(p.Id, new HashSet<Project>());
-    //  }
-
-    //  foreach (var p in projects) {
-    //    var parentProjectId = p.ParentProjectId;
-    //    while (parentProjectId != null) {
-    //      var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
-    //      if (parent != null) {
-    //        projectAncestors[p.Id].Add(parent);
-    //        projectDescendants[parent.Id].Add(p);
-    //        parentProjectId = parent.ParentProjectId;
-    //      } else {
-    //        parentProjectId = null;
-    //      }
-    //    }
-    //  }
-    //}
 
     private void UpdateResourceGenealogy() {
@@ -314,21 +257,18 @@
     }
 
-    public void RefreshJobs() {
-      var projectIds = new List<Guid>();
-      jobs = new Dictionary<Guid, HiveItemCollection<RefreshableJob>>();
-      tasks = new Dictionary<Guid, List<LightweightTask>>();
-
+    public void RefreshJobs(Guid projectId) {
       HiveServiceLocator.Instance.CallHiveService(service => {
-        service.GetProjectsForAdministration().ForEach(p => projectIds.Add(p.Id));
-        if(projectIds.Any()) {
-          projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<RefreshableJob>()));
-          var unsortedJobs = service.GetJobsByProjectIds(projectIds)
-            .OrderBy(x => x.DateCreated).ToList();
-          
+        var projectIds = new HashSet<Guid>(service.GetProjectsForAdministration().Select(x => x.Id));
+        if (projectIds.Contains(projectId)) {
+          jobs.Add(projectId, new HiveItemCollection<RefreshableJob>());
+
+          var unsortedJobs = service.GetJobsByProjectId(projectId)
+                                    .OrderBy(x => x.DateCreated).ToList();
+
           unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
           unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
           unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
 
-          foreach(var job in jobs.SelectMany(x => x.Value))
+          foreach (var job in jobs.SelectMany(x => x.Value))
             LoadLightweightJob(job);
         }
@@ -344,11 +284,11 @@
         tasks[job.Id].AddRange(lightweightTasks);
       } else {
-        tasks.Add(job.Id, new List<LightweightTask>(lightweightTasks));        
+        tasks.Add(job.Id, new List<LightweightTask>(lightweightTasks));
       }
 
       if (lightweightTasks != null && lightweightTasks.Count > 0 && lightweightTasks.All(x => x.Id != Guid.Empty)) {
         if (lightweightTasks.All(x =>
-          x.State == TaskState.Finished 
-          || x.State == TaskState.Aborted 
+          x.State == TaskState.Finished
+          || x.State == TaskState.Aborted
           || x.State == TaskState.Failed)) {
           refreshableJob.ExecutionState = ExecutionState.Stopped;
@@ -366,6 +306,6 @@
           refreshableJob.ExecutionState = ExecutionState.Paused;
           refreshableJob.RefreshAutomatically = false;
-        } else if (lightweightTasks.Any(x => x.State == TaskState.Calculating 
-                                  || x.State == TaskState.Transferring 
+        } else if (lightweightTasks.Any(x => x.State == TaskState.Calculating
+                                  || x.State == TaskState.Transferring
                                   || x.State == TaskState.Waiting)) {
           refreshableJob.ExecutionState = ExecutionState.Started;
@@ -377,5 +317,5 @@
 
     public void SortJobs() {
-      for(int i = 0; i < jobs.Count; i++) {
+      for (int i = 0; i < jobs.Count; i++) {
         var projectId = jobs.Keys.ElementAt(i);
         var unsortedJobs = jobs.Values.ElementAt(i);
@@ -403,9 +343,7 @@
             service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
           });
-        }
-        catch {
+        } catch {
           throw;
-        }
-        finally {
+        } finally {
           OnRefreshed();
         }
@@ -521,5 +459,5 @@
 
     public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
-      if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
+      if (projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
       else return Enumerable.Empty<Project>();
     }
@@ -545,5 +483,5 @@
 
     public bool CheckAccessToAdminAreaGranted() {
-      if(projects != null) {
+      if (projects != null) {
         return projects.Count > 0;
       } else {
@@ -561,5 +499,5 @@
       if (res.OwnerUserId == userId) {
         return true;
-      } else if(resourceAncestors.ContainsKey(res.Id)) {
+      } else if (resourceAncestors.ContainsKey(res.Id)) {
         return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any();
       }
@@ -583,5 +521,5 @@
       if (pro == null || userId == Guid.Empty) return false;
 
-      if(projectAncestors.ContainsKey(pro.Id)) {
+      if (projectAncestors.ContainsKey(pro.Id)) {
         return GetAvailableProjectAncestors(pro.Id).Any(x => x.OwnerUserId == userId);
       }
@@ -613,5 +551,5 @@
         // ... if the user is no admin nor owner of the new parent or grand..grandparents
         changePossible = false;
-      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
+      } else if (parent != null && projectDescendants.ContainsKey(child.Id)) {
         // ... if the new parent is among the moved project's descendants
         changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
@@ -630,5 +568,5 @@
       // ... or the new parent is a slave
       // ... or there is not parental change
-      if (child == null 
+      if (child == null
         || child == parent
         || (parent != null && parent.Id == Guid.Empty)
@@ -645,5 +583,5 @@
 
     public IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
-      var assignedJobResource =  HiveServiceLocator.Instance.CallHiveService(service => service.GetAssignedResourcesForJob(jobId));
+      var assignedJobResource = HiveServiceLocator.Instance.CallHiveService(service => service.GetAssignedResourcesForJob(jobId));
       return Resources.Where(x => assignedJobResource.Select(y => y.ResourceId).Contains(x.Id));
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/GenerateServiceClients.cmd
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/GenerateServiceClients.cmd	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/GenerateServiceClients.cmd	(revision 16892)
@@ -13,5 +13,5 @@
 IF "%GENERATECONFIG%"=="" SET GENERATECONFIG=y
 
-SET ARGS=http://%HOST%/Hive-3.3/HiveService.svc?wsdl ^
+SET ARGS=http://%HOST%/Hive-3.4/HiveService.svc?wsdl ^
 /out:HiveServiceClient ^
 /namespace:*,HeuristicLab.Clients.Hive ^
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Core/3.3/Interfaces/IValueParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Core/3.3/Interfaces/IValueParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Core/3.3/Interfaces/IValueParameter.cs	(revision 16892)
@@ -27,6 +27,8 @@
   public interface IValueParameter : IParameter {
     IItem Value { get; set; }
+    bool ReadOnly { get; set; }
     bool GetsCollected { get; set; }
     event EventHandler ValueChanged;
+    event EventHandler ReadOnlyChanged;
     event EventHandler GetsCollectedChanged;
   }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs	(revision 16892)
@@ -35,5 +35,24 @@
     {
       {"ProgramRootSymbol", "Prog"},
-      {"StartSymbol","RPB"}
+      {"StartSymbol","RPB"},
+      // short form 
+      {"Subtraction", "-" },
+      {"Addition", "+" },
+      {"Multiplication", "*" },
+      {"Division", "/" },
+      {"Absolute", "abs" },
+      {"AnalyticQuotient", "AQ" },
+      {"Sine", "sin" },
+      {"Cosine", "cos" },
+      {"Tanget", "tan" },
+      {"HyperbolicTangent", "tanh" },
+      {"Exponential", "exp" },
+      {"Logarithm", "log" },
+      {"SquareRoot", "sqrt" },
+      {"Square", "sqr" },
+      {"CubeRoot", "cbrt" },
+      {"Cube", "cube" },
+      {"GreaterThan", ">" },
+      {"LessThan", "<" },
     };
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Crossovers/SubtreeCrossover.cs	(revision 16892)
@@ -105,5 +105,5 @@
       double internalCrossoverPointProbability, int maxTreeLength, int maxTreeDepth, double crossoverProbability = 1.0) {
       if (random.NextDouble() >= crossoverProbability) {
-        return random.NextDouble() < 0.5 ? parent0 : parent1;
+        return parent0;
       }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeGraphvizFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeGraphvizFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeGraphvizFormatter.cs	(revision 16892)
@@ -33,5 +33,25 @@
       // match Koza style
       {"ProgramRootSymbol", "Prog"},
-      {"StartSymbol", "RPB"}, 
+      {"StartSymbol", "RPB"},
+
+      // short form 
+      {"Subtraction", "-" },
+      {"Addition", "+" },
+      {"Multiplication", "*" },
+      {"Division", "/" },
+      {"Absolute", "abs" },
+      {"AnalyticQuotient", "AQ" },
+      {"Sine", "sin" },
+      {"Cosine", "cos" },
+      {"Tanget", "tan" },
+      {"HyperbolicTangent", "tanh" },
+      {"Exponential", "exp" },
+      {"Logarithm", "log" },
+      {"SquareRoot", "sqrt" },
+      {"Square", "sqr" },
+      {"CubeRoot", "cbrt" },
+      {"Cube", "cube" },
+      {"GreaterThan", ">" },
+      {"LessThan", "<" },
     };
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs.sln
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs.sln	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs.sln	(revision 16892)
@@ -67,7 +67,7 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.EPPlus-4.0.3", "HeuristicLab.ExtLibs\HeuristicLab.EPPlus\4.0.3\HeuristicLab.EPPlus-4.0.3\HeuristicLab.EPPlus-4.0.3.csproj", "{675A6EE4-DE7C-413E-8BEF-EB21E0384C87}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimSharp-3.0.11", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.0.11\SimSharp-3.0.11\SimSharp-3.0.11.csproj", "{9FE9C740-7859-4D01-AD07-7D4E15A6320B}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.SimSharp-3.0.11", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.0.11\HeuristicLab.SimSharp-3.0.11\HeuristicLab.SimSharp-3.0.11.csproj", "{5C93CAF7-AE6A-4540-95B2-5DA6761A2677}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimSharp-3.1.1", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.1.1\SimSharp-3.1.1\SimSharp-3.1.1.csproj", "{9FE9C740-7859-4D01-AD07-7D4E15A6320B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.SimSharp-3.1.1", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.1.1\HeuristicLab.SimSharp-3.1.1\HeuristicLab.SimSharp-3.1.1.csproj", "{5C93CAF7-AE6A-4540-95B2-5DA6761A2677}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.IGraph-0.8.0-pre", "HeuristicLab.ExtLibs\HeuristicLab.Igraph\0.8.0-pre\HeuristicLab.Igraph-0.8.0-pre\HeuristicLab.IGraph-0.8.0-pre.csproj", "{088D34F2-32EA-43FF-BAA8-22428D5B66BE}"
@@ -78,4 +78,6 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Attic", "HeuristicLab.ExtLibs\HeuristicLab.Attic\1.0.0\HeuristicLab.Attic.csproj", "{44A10478-D290-43C2-9757-F08F5292FEA5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Protobuf", "HeuristicLab.ExtLibs\HeuristicLab.Protobuf\3.6.1\HeuristicLab.Protobuf.csproj", "{44B10478-D290-43D3-9757-C08F5292FEA5}"
 EndProject
 Global
@@ -505,4 +507,16 @@
 		{44A10478-D290-43C2-9757-F08F5292FEA5}.Release|x86.ActiveCfg = Release|Any CPU
 		{44A10478-D290-43C2-9757-F08F5292FEA5}.Release|x86.Build.0 = Release|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Debug|x64.Build.0 = Debug|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Debug|x86.Build.0 = Debug|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Release|x64.ActiveCfg = Release|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Release|x64.Build.0 = Release|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Release|x86.ActiveCfg = Release|Any CPU
+		{44B10478-D290-43D3-9757-C08F5292FEA5}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Attic/1.0.0/HeuristicLab.Attic.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Attic/1.0.0/HeuristicLab.Attic.csproj	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Attic/1.0.0/HeuristicLab.Attic.csproj	(revision 16892)
@@ -36,7 +36,4 @@
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
-      <HintPath>..\..\..\..\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
-    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -64,6 +61,17 @@
   <ItemGroup>
     <PackageReference Include="HEAL.Attic">
-      <Version>1.0.0-pre04</Version>
+      <Version>1.0.0</Version>
     </PackageReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186a6a-5176-4402-ae83-886557b53cca}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Protobuf\3.6.1\HeuristicLab.Protobuf.csproj">
+      <Project>{44b10478-d290-43d3-9757-c08f5292fea5}</Project>
+      <Name>HeuristicLab.Protobuf</Name>
+    </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Attic/1.0.0/Plugin.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Attic/1.0.0/Plugin.cs.frame	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Attic/1.0.0/Plugin.cs.frame	(revision 16892)
@@ -31,6 +31,6 @@
   [PluginFile("HEAL.Attic.dll", PluginFileType.Assembly)]
   [PluginFile("HEAL.Attic.License.txt", PluginFileType.License)]
-  [PluginFile("Google.Protobuf.dll", PluginFileType.Assembly)]
   [PluginFile("System.Drawing.Common.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Protobuf", "3.6.1")]
   public class Plugin : PluginBase {
   }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/instruction.h	(revision 16892)
@@ -9,23 +9,24 @@
 {
     // same values as in OpCodes.cs
-    Add = 1,
-    Sub = 2,
-    Mul = 3,
-    Div = 4,
-    Sin = 5,
-    Cos = 6,
-    Tan = 7,
-    Log = 8,
-    Exp = 9,
-    Var = 18,
-    Const = 20,
-    Power = 22,
-    Root = 23,
-    Square = 28,
-    Sqrt = 29,
-    Absolute = 48,
+    Add                = 1,
+    Sub                = 2,
+    Mul                = 3,
+    Div                = 4,
+    Sin                = 5,
+    Cos                = 6,
+    Tan                = 7,
+    Log                = 8,
+    Exp                = 9,
+    Var                = 18,
+    Const              = 20,
+    Power              = 22,
+    Root               = 23,
+    Square             = 28,
+    Sqrt               = 29,
+    Absolute           = 48,
     AnalyticalQuotient = 49,
-    Cube = 50,
-    CubeRoot = 51
+    Cube               = 50,
+    CubeRoot           = 51,
+    Tanh               = 52
 };
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/interpreter.h	(revision 16892)
@@ -64,25 +64,30 @@
             case OpCodes::Exp:
                 {
-                    in.value = std::exp(code[in.childIndex].value);
+                    in.value = hl_exp(code[in.childIndex].value);
                     break;
                 }
             case OpCodes::Log:
                 {
-                    in.value = std::log(code[in.childIndex].value);
+                    in.value = hl_log(code[in.childIndex].value);
                     break;
                 }
             case OpCodes::Sin:
                 {
-                    in.value = std::sin(code[in.childIndex].value);
+                    in.value = hl_sin(code[in.childIndex].value);
                     break;
                 }
             case OpCodes::Cos:
                 {
-                    in.value = std::cos(code[in.childIndex].value);
+                    in.value = hl_cos(code[in.childIndex].value);
                     break;
                 }
             case OpCodes::Tan:
                 {
-                    in.value = std::tan(code[in.childIndex].value);
+                    in.value = hl_tan(code[in.childIndex].value);
+                    break;
+                }
+            case OpCodes::Tanh:
+                {
+                    in.value = hl_tanh(code[in.childIndex].value);
                     break;
                 }
@@ -90,6 +95,6 @@
                 {
                     double x = code[in.childIndex].value;
-                    double y = std::round(code[in.childIndex + 1].value);
-                    in.value = std::pow(x, y);
+                    double y = hl_round(code[in.childIndex + 1].value);
+                    in.value = hl_pow(x, y);
                     break;
                 }
@@ -97,26 +102,26 @@
                 {
                     double x = code[in.childIndex].value;
-                    double y = std::round(code[in.childIndex + 1].value);
-                    in.value = std::pow(x, 1 / y);
+                    double y = hl_round(code[in.childIndex + 1].value);
+                    in.value = hl_pow(x, 1 / y);
                     break;
                 }
             case OpCodes::Sqrt:
                 {
-                    in.value = std::pow(code[in.childIndex].value, 1./2.);
+                    in.value = hl_pow(code[in.childIndex].value, 1./2.);
                     break;
                 }
             case OpCodes::Square:
                 {
-                    in.value = std::pow(code[in.childIndex].value, 2.);
+                    in.value = hl_pow(code[in.childIndex].value, 2.);
                     break;
                 }
             case OpCodes::CubeRoot:
                 {
-                    in.value = std::pow(code[in.childIndex].value, 1./3.);
+                    in.value = hl_pow(code[in.childIndex].value, 1./3.);
                     break;
                 }
             case OpCodes::Cube:
                 {
-                    in.value = std::pow(code[in.childIndex].value, 3.);
+                    in.value = hl_pow(code[in.childIndex].value, 3.);
                     break;
                 }
@@ -130,5 +135,5 @@
                     double x = code[in.childIndex].value;
                     double y = code[in.childIndex + 1].value;
-                    in.value = x / std::sqrt(1 + y*y);
+                    in.value = x / hl_sqrt(1 + y*y);
                     break;
                 }
@@ -228,4 +233,9 @@
                     break;
                 }
+            case OpCodes::Tanh:
+                {
+                    tanh(in.buf, code[in.childIndex].buf);
+                    break;
+                }
             case OpCodes::Log:
                 {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/vector_operations.h
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/vector_operations.h	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.NativeInterpreter/0.1/NativeInterpreter-0.1/src/vector_operations.h	(revision 16892)
@@ -14,7 +14,9 @@
 #define hl_cos vdt::fast_cos
 #define hl_tan vdt::fast_tan
+#define hl_tanh vdt::fast_tanh
 #define hl_sqrt vdt::fast_sqrt
 #define hl_pow vdt::fast_pow
 #define hl_round vdt::fast_round
+#define hl_inv vdt::fast_inv
 #else
 #define hl_exp std::exp
@@ -23,7 +25,10 @@
 #define hl_cos std::cos
 #define hl_tan std::tan
+#define hl_tanh std::tanh
 #define hl_sqrt std::sqrt
 #define hl_pow std::pow
 #define hl_round std::round
+#define hl_inv(x) 1. / x;
+
 #endif
 
@@ -47,9 +52,10 @@
 inline void cos(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_cos(b[i]); }
 inline void tan(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_tan(b[i]); }
+inline void tanh(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_tanh(b[i]); }
 inline void sqrt(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_sqrt(b[i]); }
 inline void pow(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_pow(a[i], hl_round(b[i])); };
 inline void root(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_pow(a[i], 1. / hl_round(b[i])); };
 inline void square(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_pow(b[i], 2.); };
-inline void inv(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = 1. / b[i]; }
+inline void inv(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = hl_inv(b[i]); }
 inline void neg(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = -b[i]; }
 inline void abs(double* __restrict a, double const * __restrict b) noexcept { FOR(i) a[i] = std::fabs(b[i]); }
@@ -66,9 +72,11 @@
 // vector operations
 inline void neg(double* __restrict a) noexcept { FOR(i) a[i] = -a[i]; }
-inline void inv(double* __restrict a) noexcept { FOR(i) a[i] = 1. / a[i]; }
+inline void inv(double* __restrict a) noexcept { FOR(i) a[i] = hl_inv(a[i]); }
 inline void exp(double* __restrict a) noexcept { FOR(i) a[i] = hl_exp(a[i]); }
 inline void log(double* __restrict a) noexcept { FOR(i) a[i] = hl_log(a[i]); }
 inline void sin(double* __restrict a) noexcept { FOR(i) a[i] = hl_sin(a[i]); }
 inline void cos(double* __restrict a) noexcept { FOR(i) a[i] = hl_cos(a[i]); }
+inline void tan(double* __restrict a) noexcept { FOR(i) a[i] = hl_tan(a[i]); }
+inline void tanh(double* __restrict a) noexcept { FOR(i) a[i] = hl_tanh(a[i]); }
 inline void round(double* __restrict a) noexcept { FOR(i) a[i] = hl_round(a[i]); }
 inline void square(double* __restrict a) noexcept { FOR(i) a[i] = hl_pow(a[i], 2.); }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Google.Protobuf.License.txt
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Google.Protobuf.License.txt	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Google.Protobuf.License.txt	(revision 16892)
@@ -0,0 +1,32 @@
+﻿Copyright 2008 Google Inc.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it.  This code is not
+standalone and requires a support library to be linked with it.  This
+support library is itself covered by the above license.
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/HeuristicLab.Protobuf.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/HeuristicLab.Protobuf.csproj	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/HeuristicLab.Protobuf.csproj	(revision 16892)
@@ -0,0 +1,89 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{44B10478-D290-43D3-9757-C08F5292FEA5}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Protobuf</RootNamespace>
+    <AssemblyName>HeuristicLab.Protobuf</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <Deterministic>true</Deterministic>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Plugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Google.Protobuf.License.txt">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Google.Protobuf">
+      <Version>3.6.1</Version>
+    </PackageReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186a6a-5176-4402-ae83-886557b53cca}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Plugin.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Plugin.cs.frame	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Plugin.cs.frame	(revision 16892)
@@ -0,0 +1,34 @@
+﻿#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 System.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Protobuf {
+  [Plugin("HeuristicLab.Protobuf","HeuristicLab wrapper for Google.Protobuf nuget package","3.6.1.$WCREV$")]  
+  [PluginFile("HeuristicLab.Protobuf.dll", PluginFileType.Assembly)]
+  [PluginFile("Google.Protobuf.dll", PluginFileType.Assembly)]
+  [PluginFile("Google.Protobuf.License.txt", PluginFileType.License)]
+  public class Plugin : PluginBase { }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Properties/AssemblyInfo.cs.frame	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.Protobuf/3.6.1/Properties/AssemblyInfo.cs.frame	(revision 16892)
@@ -0,0 +1,58 @@
+﻿#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.CompilerServices;
+using System.Runtime.InteropServices;
+using HeuristicLab.PluginInfrastructure;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Protobuf")]
+[assembly: AssemblyDescription("Provides an interface to Google.Protobuf nuget package.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+// [assembly: Guid("44a10478-d290-43c2-9757-f08f5292fea5")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.6.1")]
+[assembly: AssemblyFileVersion("3.6.1.$WCREV$")]
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/HeuristicLab.SimSharp-3.1.1.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/HeuristicLab.SimSharp-3.1.1.csproj	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/HeuristicLab.SimSharp-3.1.1.csproj	(revision 16892)
@@ -0,0 +1,128 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{5C93CAF7-AE6A-4540-95B2-5DA6761A2677}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.SimSharp</RootNamespace>
+    <AssemblyName>HeuristicLab.SimSharp-3.1.1</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="Plugin.cs" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186a6a-5176-4402-ae83-886557b53cca}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\SimSharp-3.1.1\SimSharp-3.1.1.csproj">
+      <Project>{9fe9c740-7859-4d01-ad07-7d4e15a6320b}</Project>
+      <Name>SimSharp-3.1.1</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="SimSharp-3.1.1 License.txt">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">
+      set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+      set ProjectDir=$(ProjectDir)
+      set SolutionDir=$(SolutionDir)
+      set Outdir=$(Outdir)
+
+      call PreBuildEvent.cmd
+    </PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+      export ProjectDir=$(ProjectDir)
+      export SolutionDir=$(SolutionDir)
+
+      $SolutionDir/PreBuildEvent.sh
+    </PreBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Plugin.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Plugin.cs.frame	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Plugin.cs.frame	(revision 16892)
@@ -0,0 +1,31 @@
+﻿#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.SimSharp {
+  [Plugin("HeuristicLab.SimSharp", "Transport plugin for the simulation framework Sim#", "3.1.1.$WCREV$")]
+  [PluginFile("HeuristicLab.SimSharp-3.1.1.dll", PluginFileType.Assembly)]
+  [PluginFile("SimSharp-3.1.1.dll", PluginFileType.Assembly)]
+  [PluginFile("SimSharp-3.1.1 License.txt", PluginFileType.License)]
+  public class HeuristicLabSimSharpPlugin : PluginBase {
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Properties/AssemblyInfo.cs.frame	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Properties/AssemblyInfo.cs.frame	(revision 16892)
@@ -0,0 +1,35 @@
+﻿using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.SimSharp")]
+[assembly: AssemblyDescription("Transport plugin for the simulation framework Sim#")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("15bc80f5-e0b9-4481-bab1-289d1403f877")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.1.1.0")]
+[assembly: AssemblyFileVersion("3.1.1.$WCREV$")]
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/SimSharp-3.1.1 License.txt
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/SimSharp-3.1.1 License.txt	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/SimSharp-3.1.1 License.txt	(revision 16892)
@@ -0,0 +1,705 @@
+Sim# integrates code from a third-party "BlueRaja". Below the license from that
+third party provider as well as Sim#'s own license are given.
+Sim# also uses FastRandom from Colin Green (sharpneat@gmail.com) which is also
+licensed under the GPL. 
+
+=== License of BlueRaja's Event Queue ===
+
+The MIT License (MIT)
+
+Copyright (c) 2013 Daniel "BlueRaja" Pflughoeft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+=== License of SimSharp and FastRandom ===
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Analysis/ContinuousStatistics.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Analysis/ContinuousStatistics.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Analysis/ContinuousStatistics.cs	(revision 16892)
@@ -0,0 +1,72 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public sealed class ContinuousStatistics {
+    private readonly Simulation env;
+
+    public int Count { get; private set; }
+    public double TotalTimeD { get; private set; }
+    public TimeSpan TotalTime { get { return env.ToTimeSpan(TotalTimeD); } }
+
+    public double Min { get; private set; }
+    public double Max { get; private set; }
+    public double Area { get; private set; }
+    public double Mean { get; private set; }
+    public double StdDev { get { return Math.Sqrt(Variance); } }
+    public double Variance { get { return (TotalTimeD > 0) ? variance / TotalTimeD : 0.0; } }
+
+    private double lastUpdateTime;
+    private double lastValue;
+    private double variance;
+
+    private bool firstSample;
+
+
+    public ContinuousStatistics(Simulation env) {
+      this.env = env;
+      lastUpdateTime = env.NowD;
+    }
+
+    public void Update(double value) {
+      Count++;
+
+      if (!firstSample) {
+        Min = Max = Mean = value;
+        firstSample = true;
+      } else {
+        if (value < Min) Min = value;
+        if (value > Max) Max = value;
+
+        var duration = env.NowD - lastUpdateTime;
+        if (duration > 0) {
+          Area += (lastValue * duration);
+          var oldMean = Mean;
+          Mean = oldMean + (lastValue - oldMean) * duration / (duration + TotalTimeD);
+          variance = variance + (lastValue - oldMean) * (lastValue - Mean) * duration;
+          TotalTimeD += duration;
+        }
+      }
+
+      lastUpdateTime = env.NowD;
+      lastValue = value;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue-License.txt
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue-License.txt	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue-License.txt	(revision 16892)
@@ -0,0 +1,21 @@
+﻿The MIT License (MIT)
+
+Copyright (c) 2013 Daniel "BlueRaja" Pflughoeft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue.cs	(revision 16892)
@@ -0,0 +1,276 @@
+﻿using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// An implementation of a min-Priority Queue using a heap.  Has O(1) .Contains()!
+  /// See https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp/wiki/Getting-Started for more information
+  /// </summary>
+  /// <remarks>
+  /// There are modifications so that the type is not generic anymore and can only hold values of type EventQueueNode
+  /// </remarks>
+  public sealed class EventQueue : IEnumerable<EventQueueNode> {
+    private int _numNodes;
+    private readonly EventQueueNode[] _nodes;
+    private long _numNodesEverEnqueued;
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">EventQueueNodehe max nodes ever allowed to be enqueued (going over this will cause an exception)</param>
+    public EventQueue(int maxNodes) {
+      _numNodes = 0;
+      _nodes = new EventQueueNode[maxNodes + 1];
+      _numNodesEverEnqueued = 0;
+    }
+
+    /// <summary>
+    /// Returns the number of nodes in the queue.  O(1)
+    /// </summary>
+    public int Count {
+      get {
+        return _numNodes;
+      }
+    }
+
+    /// <summary>
+    /// Returns the maximum number of items that can be enqueued at once in this queue.  Once you hit this number (ie. once Count == MaxSize),
+    /// attempting to enqueue another item will throw an exception.  O(1)
+    /// </summary>
+    public int MaxSize {
+      get {
+        return _nodes.Length - 1;
+      }
+    }
+
+    /// <summary>
+    /// Removes every node from the queue.  O(n) (So, don't do this often!)
+    /// </summary>
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    public void Clear() {
+      Array.Clear(_nodes, 1, _numNodes);
+      _numNodes = 0;
+    }
+
+    /// <summary>
+    /// Returns (in O(1)!) whether the given node is in the queue.  O(1)
+    /// </summary>
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    public bool Contains(EventQueueNode node) {
+      return (_nodes[node.QueueIndex] == node);
+    }
+
+    /// <summary>
+    /// Enqueue a node - .Priority must be set beforehand!  O(log n)
+    /// </summary>
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    public EventQueueNode Enqueue(DateTime primaryPriority, Event @event, int secondaryPriority = 0) {
+      var node = new EventQueueNode {
+        PrimaryPriority = primaryPriority,
+        SecondaryPriority = secondaryPriority,
+        Event = @event,
+        QueueIndex = ++_numNodes,
+        InsertionIndex = _numNodesEverEnqueued++
+      };
+      _nodes[_numNodes] = node;
+      CascadeUp(_nodes[_numNodes]);
+      return node;
+    }
+    
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    private void Swap(EventQueueNode node1, EventQueueNode node2) {
+      //Swap the nodes
+      _nodes[node1.QueueIndex] = node2;
+      _nodes[node2.QueueIndex] = node1;
+
+      //Swap their indicies
+      int temp = node1.QueueIndex;
+      node1.QueueIndex = node2.QueueIndex;
+      node2.QueueIndex = temp;
+    }
+
+    //Performance appears to be slightly better when this is NOT inlined o_O
+    private void CascadeUp(EventQueueNode node) {
+      //aka Heapify-up
+      int parent = node.QueueIndex / 2;
+      while (parent >= 1) {
+        EventQueueNode parentNode = _nodes[parent];
+        if (HasHigherPriority(parentNode, node))
+          break;
+
+        //Node has lower priority value, so move it up the heap
+        Swap(node, parentNode); //For some reason, this is faster with Swap() rather than (less..?) individual operations, like in CascadeDown()
+
+        parent = node.QueueIndex / 2;
+      }
+    }
+
+
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    private void CascadeDown(EventQueueNode node) {
+      //aka Heapify-down
+      EventQueueNode newParent;
+      int finalQueueIndex = node.QueueIndex;
+      while (true) {
+        newParent = node;
+        int childLeftIndex = 2 * finalQueueIndex;
+
+        //Check if the left-child is higher-priority than the current node
+        if (childLeftIndex > _numNodes) {
+          //This could be placed outside the loop, but then we'd have to check newParent != node twice
+          node.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = node;
+          break;
+        }
+
+        EventQueueNode childLeft = _nodes[childLeftIndex];
+        if (HasHigherPriority(childLeft, newParent)) {
+          newParent = childLeft;
+        }
+
+        //Check if the right-child is higher-priority than either the current node or the left child
+        int childRightIndex = childLeftIndex + 1;
+        if (childRightIndex <= _numNodes) {
+          EventQueueNode childRight = _nodes[childRightIndex];
+          if (HasHigherPriority(childRight, newParent)) {
+            newParent = childRight;
+          }
+        }
+
+        //If either of the children has higher (smaller) priority, swap and continue cascading
+        if (newParent != node) {
+          //Move new parent to its new index.  node will be moved once, at the end
+          //Doing it this way is one less assignment operation than calling Swap()
+          _nodes[finalQueueIndex] = newParent;
+
+          int temp = newParent.QueueIndex;
+          newParent.QueueIndex = finalQueueIndex;
+          finalQueueIndex = temp;
+        } else {
+          //See note above
+          node.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = node;
+          break;
+        }
+      }
+    }
+
+    /// <summary>
+    /// Returns true if 'higher' has higher priority than 'lower', false otherwise.
+    /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
+    /// </summary>
+
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    private bool HasHigherPriority(EventQueueNode higher, EventQueueNode lower) {
+      return (higher.PrimaryPriority < lower.PrimaryPriority ||
+          (higher.PrimaryPriority == lower.PrimaryPriority
+            && (higher.SecondaryPriority < lower.SecondaryPriority ||
+            (higher.SecondaryPriority == lower.SecondaryPriority
+              && higher.InsertionIndex < lower.InsertionIndex))));
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with highest priority; ties are broken by order of insertion), and returns it.  O(log n)
+    /// </summary>
+    public EventQueueNode Dequeue() {
+      EventQueueNode returnMe = _nodes[1];
+      Remove(returnMe);
+      return returnMe;
+    }
+
+    /// <summary>
+    /// Returns the head of the queue, without removing it (use Dequeue() for that).  O(1)
+    /// </summary>
+    public EventQueueNode First {
+      get {
+        return _nodes[1];
+      }
+    }
+
+    /// <summary>
+    /// This method must be called on a node every time its priority changes while it is in the queue.  
+    /// <b>Forgetting to call this method will result in a corrupted queue!</b>
+    /// O(log n)
+    /// </summary>
+
+    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+    public void UpdatePriority(EventQueueNode node, DateTime primaryPriority, int secondaryPriority) {
+      node.PrimaryPriority = primaryPriority;
+      node.SecondaryPriority = secondaryPriority;
+      OnNodeUpdated(node);
+    }
+
+    internal void OnNodeUpdated(EventQueueNode node) {
+      //Bubble the updated node up or down as appropriate
+      int parentIndex = node.QueueIndex / 2;
+      EventQueueNode parentNode = _nodes[parentIndex];
+
+      if (parentIndex > 0 && HasHigherPriority(node, parentNode)) {
+        CascadeUp(node);
+      } else {
+        //Note that CascadeDown will be called if parentNode == node (that is, node is the root)
+        CascadeDown(node);
+      }
+    }
+
+    /// <summary>
+    /// Removes a node from the queue.  Note that the node does not need to be the head of the queue.  O(log n)
+    /// </summary>
+    public void Remove(EventQueueNode node) {
+      if (!Contains(node)) {
+        return;
+      }
+      if (_numNodes <= 1) {
+        _nodes[1] = null;
+        _numNodes = 0;
+        return;
+      }
+
+      //Make sure the node is the last node in the queue
+      bool wasSwapped = false;
+      EventQueueNode formerLastNode = _nodes[_numNodes];
+      if (node.QueueIndex != _numNodes) {
+        //Swap the node with the last node
+        Swap(node, formerLastNode);
+        wasSwapped = true;
+      }
+
+      _numNodes--;
+      _nodes[node.QueueIndex] = null;
+
+      if (wasSwapped) {
+        //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate
+        OnNodeUpdated(formerLastNode);
+      }
+    }
+
+    public IEnumerator<EventQueueNode> GetEnumerator() {
+      for (int i = 1; i <= _numNodes; i++)
+        yield return _nodes[i];
+    }
+
+    IEnumerator IEnumerable.GetEnumerator() {
+      return GetEnumerator();
+    }
+
+    /// <summary>
+    /// <b>Should not be called in production code.</b>
+    /// Checks to make sure the queue is still in a valid state.  Used for testing/debugging the queue.
+    /// </summary>
+    public bool IsValidQueue() {
+      for (int i = 1; i < _nodes.Length; i++) {
+        if (_nodes[i] != null) {
+          int childLeftIndex = 2 * i;
+          if (childLeftIndex < _nodes.Length && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i]))
+            return false;
+
+          int childRightIndex = childLeftIndex + 1;
+          if (childRightIndex < _nodes.Length && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i]))
+            return false;
+        }
+      }
+      return true;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueueNode.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueueNode.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueueNode.cs	(revision 16892)
@@ -0,0 +1,40 @@
+﻿using System;
+
+namespace SimSharp {
+  public class EventQueueNode {
+    /// <summary>
+    /// The Priority to insert this node at. Must be set BEFORE adding a node to the queue.
+    /// </summary>
+    public DateTime PrimaryPriority { get; set; }
+
+    /// <summary>
+    /// An integer priority that will be used to distinguish nodes with the same
+    /// <see cref="PrimaryPriority"/> and before the <see cref="InsertionIndex"/> is used.
+    /// Must be set BEFORE adding a node to the queue.
+    /// </summary>
+    /// <remarks>
+    /// A lower value means higher priority, thus int.MinValue has highest priority.
+    /// </remarks>
+    public int SecondaryPriority { get; set; }
+
+    /// <summary>
+    /// The event that is associated with this node.
+    /// </summary>
+    public Event Event { get; set; }
+
+    /// <summary>
+    /// <b>Used by the priority queue - do not edit this value.</b>
+    /// Represents the order the node was inserted in
+    /// </summary>
+    /// <remarks>
+    /// This is unique among all inserted nodes and thus represents the third and final priority.
+    /// </remarks>
+    public long InsertionIndex { get; set; }
+
+    /// <summary>
+    /// <b>Used by the priority queue - do not edit this value.</b>
+    /// Represents the current position in the queue
+    /// </summary>
+    public int QueueIndex { get; set; }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/Extensions.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/Extensions.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/Extensions.cs	(revision 16892)
@@ -0,0 +1,47 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SimSharp {
+  public static class Extensions {
+    public static IEnumerable<T> MaxItems<T>(this IEnumerable<T> source, Func<T, IComparable> selector) {
+      var enumerator = source.GetEnumerator();
+      if (!enumerator.MoveNext()) return Enumerable.Empty<T>();
+      var item = enumerator.Current;
+      var max = selector(item);
+      var result = new List<T> { item };
+      
+      while (enumerator.MoveNext()) {
+        item = enumerator.Current;
+        var comparable = selector(item);
+        var comparison = comparable.CompareTo(max);
+        if (comparison > 0) {
+          result.Clear();
+          result.Add(item);
+          max = comparable;
+        } else if (comparison == 0) {
+          result.Add(item);
+        }
+      }
+      return result;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/GenericPriorityQueue.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/GenericPriorityQueue.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/GenericPriorityQueue.cs	(revision 16892)
@@ -0,0 +1,933 @@
+﻿#region License
+/*
+The MIT License (MIT)
+
+Copyright (c) 2013 Daniel "BlueRaja" Pflughoeft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace SimSharp {
+  /// <summary>
+  /// A copy of StablePriorityQueue which also has generic explicit priority-type
+  /// </summary>
+  /// <remarks>
+  /// Original sources from https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+  /// </remarks>
+  /// <typeparam name="TItem">The values in the queue.  Must extend the GenericPriorityQueue class</typeparam>
+  /// <typeparam name="TPriority">The priority-type.  Must extend IComparable&lt;TPriority&gt;</typeparam>
+  public sealed class GenericPriorityQueue<TItem, TPriority> : IEnumerable<TItem>
+      where TItem : GenericPriorityQueueNode<TPriority>
+      where TPriority : IComparable<TPriority> {
+    private int _numNodes;
+    private TItem[] _nodes;
+    private long _numNodesEverEnqueued;
+    private readonly Comparison<TPriority> _comparer;
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+    public GenericPriorityQueue(int maxNodes) : this(maxNodes, Comparer<TPriority>.Default) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+    /// <param name="comparer">The comparer used to compare TPriority values.</param>
+    public GenericPriorityQueue(int maxNodes, IComparer<TPriority> comparer) : this(maxNodes, comparer.Compare) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+    /// <param name="comparer">The comparison function to use to compare TPriority values</param>
+    public GenericPriorityQueue(int maxNodes, Comparison<TPriority> comparer) {
+#if DEBUG
+      if (maxNodes <= 0) {
+        throw new InvalidOperationException("New queue size cannot be smaller than 1");
+      }
+#endif
+
+      _numNodes = 0;
+      _nodes = new TItem[maxNodes + 1];
+      _numNodesEverEnqueued = 0;
+      _comparer = comparer;
+    }
+
+    /// <summary>
+    /// Returns the number of nodes in the queue.
+    /// O(1)
+    /// </summary>
+    public int Count {
+      get {
+        return _numNodes;
+      }
+    }
+
+    /// <summary>
+    /// Returns the maximum number of items that can be enqueued at once in this queue.  Once you hit this number (ie. once Count == MaxSize),
+    /// attempting to enqueue another item will cause undefined behavior.  O(1)
+    /// </summary>
+    public int MaxSize {
+      get {
+        return _nodes.Length - 1;
+      }
+    }
+
+    /// <summary>
+    /// Removes every node from the queue.
+    /// O(n) (So, don't do this often!)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear() {
+      Array.Clear(_nodes, 1, _numNodes);
+      _numNodes = 0;
+    }
+
+    /// <summary>
+    /// Returns (in O(1)!) whether the given node is in the queue.  O(1)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(TItem node) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (node.QueueIndex < 0 || node.QueueIndex >= _nodes.Length) {
+        throw new InvalidOperationException("node.QueueIndex has been corrupted. Did you change it manually? Or add this node to another queue?");
+      }
+#endif
+
+      return (_nodes[node.QueueIndex] == node);
+    }
+
+    /// <summary>
+    /// Enqueue a node to the priority queue.  Lower values are placed in front. Ties are broken by first-in-first-out.
+    /// If the queue is full, the result is undefined.
+    /// If the node is already enqueued, the result is undefined.
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Enqueue(TItem node, TPriority priority) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (_numNodes >= _nodes.Length - 1) {
+        throw new InvalidOperationException("Queue is full - node cannot be added: " + node);
+      }
+      if (Contains(node)) {
+        throw new InvalidOperationException("Node is already enqueued: " + node);
+      }
+#endif
+
+      node.Priority = priority;
+      _numNodes++;
+      _nodes[_numNodes] = node;
+      node.QueueIndex = _numNodes;
+      node.InsertionIndex = _numNodesEverEnqueued++;
+      CascadeUp(node);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void CascadeUp(TItem node) {
+      //aka Heapify-up
+      int parent;
+      if (node.QueueIndex > 1) {
+        parent = node.QueueIndex >> 1;
+        TItem parentNode = _nodes[parent];
+        if (HasHigherPriority(parentNode, node))
+          return;
+
+        //Node has lower priority value, so move parent down the heap to make room
+        _nodes[node.QueueIndex] = parentNode;
+        parentNode.QueueIndex = node.QueueIndex;
+
+        node.QueueIndex = parent;
+      } else {
+        return;
+      }
+      while (parent > 1) {
+        parent >>= 1;
+        TItem parentNode = _nodes[parent];
+        if (HasHigherPriority(parentNode, node))
+          break;
+
+        //Node has lower priority value, so move parent down the heap to make room
+        _nodes[node.QueueIndex] = parentNode;
+        parentNode.QueueIndex = node.QueueIndex;
+
+        node.QueueIndex = parent;
+      }
+      _nodes[node.QueueIndex] = node;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void CascadeDown(TItem node) {
+      //aka Heapify-down
+      int finalQueueIndex = node.QueueIndex;
+      int childLeftIndex = 2 * finalQueueIndex;
+
+      // If leaf node, we're done
+      if (childLeftIndex > _numNodes) {
+        return;
+      }
+
+      // Check if the left-child is higher-priority than the current node
+      int childRightIndex = childLeftIndex + 1;
+      TItem childLeft = _nodes[childLeftIndex];
+      if (HasHigherPriority(childLeft, node)) {
+        // Check if there is a right child. If not, swap and finish.
+        if (childRightIndex > _numNodes) {
+          node.QueueIndex = childLeftIndex;
+          childLeft.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childLeft;
+          _nodes[childLeftIndex] = node;
+          return;
+        }
+        // Check if the left-child is higher-priority than the right-child
+        TItem childRight = _nodes[childRightIndex];
+        if (HasHigherPriority(childLeft, childRight)) {
+          // left is highest, move it up and continue
+          childLeft.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childLeft;
+          finalQueueIndex = childLeftIndex;
+        } else {
+          // right is even higher, move it up and continue
+          childRight.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childRight;
+          finalQueueIndex = childRightIndex;
+        }
+      }
+      // Not swapping with left-child, does right-child exist?
+      else if (childRightIndex > _numNodes) {
+        return;
+      } else {
+        // Check if the right-child is higher-priority than the current node
+        TItem childRight = _nodes[childRightIndex];
+        if (HasHigherPriority(childRight, node)) {
+          childRight.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childRight;
+          finalQueueIndex = childRightIndex;
+        }
+        // Neither child is higher-priority than current, so finish and stop.
+        else {
+          return;
+        }
+      }
+
+      while (true) {
+        childLeftIndex = 2 * finalQueueIndex;
+
+        // If leaf node, we're done
+        if (childLeftIndex > _numNodes) {
+          node.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = node;
+          break;
+        }
+
+        // Check if the left-child is higher-priority than the current node
+        childRightIndex = childLeftIndex + 1;
+        childLeft = _nodes[childLeftIndex];
+        if (HasHigherPriority(childLeft, node)) {
+          // Check if there is a right child. If not, swap and finish.
+          if (childRightIndex > _numNodes) {
+            node.QueueIndex = childLeftIndex;
+            childLeft.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childLeft;
+            _nodes[childLeftIndex] = node;
+            break;
+          }
+          // Check if the left-child is higher-priority than the right-child
+          TItem childRight = _nodes[childRightIndex];
+          if (HasHigherPriority(childLeft, childRight)) {
+            // left is highest, move it up and continue
+            childLeft.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childLeft;
+            finalQueueIndex = childLeftIndex;
+          } else {
+            // right is even higher, move it up and continue
+            childRight.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childRight;
+            finalQueueIndex = childRightIndex;
+          }
+        }
+        // Not swapping with left-child, does right-child exist?
+        else if (childRightIndex > _numNodes) {
+          node.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = node;
+          break;
+        } else {
+          // Check if the right-child is higher-priority than the current node
+          TItem childRight = _nodes[childRightIndex];
+          if (HasHigherPriority(childRight, node)) {
+            childRight.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childRight;
+            finalQueueIndex = childRightIndex;
+          }
+          // Neither child is higher-priority than current, so finish and stop.
+          else {
+            node.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = node;
+            break;
+          }
+        }
+      }
+    }
+
+    /// <summary>
+    /// Returns true if 'higher' has higher priority than 'lower', false otherwise.
+    /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private bool HasHigherPriority(TItem higher, TItem lower) {
+      var cmp = _comparer(higher.Priority, lower.Priority);
+      return (cmp < 0 || (cmp == 0 && higher.InsertionIndex < lower.InsertionIndex));
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+    /// If queue is empty, result is undefined
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public TItem Dequeue() {
+#if DEBUG
+      if (_numNodes <= 0) {
+        throw new InvalidOperationException("Cannot call Dequeue() on an empty queue");
+      }
+
+      if (!IsValidQueue()) {
+        throw new InvalidOperationException("Queue has been corrupted (Did you update a node priority manually instead of calling UpdatePriority()?" +
+                                            "Or add the same node to two different queues?)");
+      }
+#endif
+
+      TItem returnMe = _nodes[1];
+      //If the node is already the last node, we can remove it immediately
+      if (_numNodes == 1) {
+        _nodes[1] = null;
+        _numNodes = 0;
+        return returnMe;
+      }
+
+      //Swap the node with the last node
+      TItem formerLastNode = _nodes[_numNodes];
+      _nodes[1] = formerLastNode;
+      formerLastNode.QueueIndex = 1;
+      _nodes[_numNodes] = null;
+      _numNodes--;
+
+      //Now bubble formerLastNode (which is no longer the last node) down
+      CascadeDown(formerLastNode);
+      return returnMe;
+    }
+
+    /// <summary>
+    /// Resize the queue so it can accept more nodes.  All currently enqueued nodes are remain.
+    /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior
+    /// O(n)
+    /// </summary>
+    public void Resize(int maxNodes) {
+#if DEBUG
+      if (maxNodes <= 0) {
+        throw new InvalidOperationException("Queue size cannot be smaller than 1");
+      }
+
+      if (maxNodes < _numNodes) {
+        throw new InvalidOperationException("Called Resize(" + maxNodes + "), but current queue contains " + _numNodes + " nodes");
+      }
+#endif
+
+      TItem[] newArray = new TItem[maxNodes + 1];
+      int highestIndexToCopy = Math.Min(maxNodes, _numNodes);
+      Array.Copy(_nodes, newArray, highestIndexToCopy + 1);
+      _nodes = newArray;
+    }
+
+    /// <summary>
+    /// Returns the head of the queue, without removing it (use Dequeue() for that).
+    /// If the queue is empty, behavior is undefined.
+    /// O(1)
+    /// </summary>
+    public TItem First {
+      get {
+#if DEBUG
+        if (_numNodes <= 0) {
+          throw new InvalidOperationException("Cannot call .First on an empty queue");
+        }
+#endif
+
+        return _nodes[1];
+      }
+    }
+
+    /// <summary>
+    /// This method must be called on a node every time its priority changes while it is in the queue.  
+    /// <b>Forgetting to call this method will result in a corrupted queue!</b>
+    /// Calling this method on a node not in the queue results in undefined behavior
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void UpdatePriority(TItem node, TPriority priority) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (!Contains(node)) {
+        throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + node);
+      }
+#endif
+
+      node.Priority = priority;
+      OnNodeUpdated(node);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void OnNodeUpdated(TItem node) {
+      //Bubble the updated node up or down as appropriate
+      int parentIndex = node.QueueIndex >> 1;
+
+      if (parentIndex > 0 && HasHigherPriority(node, _nodes[parentIndex])) {
+        CascadeUp(node);
+      } else {
+        //Note that CascadeDown will be called if parentNode == node (that is, node is the root)
+        CascadeDown(node);
+      }
+    }
+
+    /// <summary>
+    /// Removes a node from the queue.  The node does not need to be the head of the queue.  
+    /// If the node is not in the queue, the result is undefined.  If unsure, check Contains() first
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Remove(TItem node) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (!Contains(node)) {
+        throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + node);
+      }
+#endif
+
+      //If the node is already the last node, we can remove it immediately
+      if (node.QueueIndex == _numNodes) {
+        _nodes[_numNodes] = null;
+        _numNodes--;
+        return;
+      }
+
+      //Swap the node with the last node
+      TItem formerLastNode = _nodes[_numNodes];
+      _nodes[node.QueueIndex] = formerLastNode;
+      formerLastNode.QueueIndex = node.QueueIndex;
+      _nodes[_numNodes] = null;
+      _numNodes--;
+
+      //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate
+      OnNodeUpdated(formerLastNode);
+    }
+
+    public IEnumerator<TItem> GetEnumerator() {
+      IEnumerable<TItem> e = new ArraySegment<TItem>(_nodes, 1, _numNodes);
+      return e.GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator() {
+      return GetEnumerator();
+    }
+
+    /// <summary>
+    /// <b>Should not be called in production code.</b>
+    /// Checks to make sure the queue is still in a valid state.  Used for testing/debugging the queue.
+    /// </summary>
+    public bool IsValidQueue() {
+      for (int i = 1; i < _nodes.Length; i++) {
+        if (_nodes[i] != null) {
+          int childLeftIndex = 2 * i;
+          if (childLeftIndex < _nodes.Length && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i]))
+            return false;
+
+          int childRightIndex = childLeftIndex + 1;
+          if (childRightIndex < _nodes.Length && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i]))
+            return false;
+        }
+      }
+      return true;
+    }
+  }
+
+  /// <summary>
+  /// A copy of StablePriorityQueue where the items themselves contain an implicit priority.
+  /// </summary>
+  /// <remarks>
+  /// Either <typeparamref name="TItem"/> implements IComparable&lt;typeparamref name="TItem"/>&gt; or
+  /// a custom comparer must be provided.
+  /// </remarks>
+  /// <typeparam name="TItem">The values in the queue. Must extend the GenericPriorityQueueNode class</typeparam>
+  public sealed class GenericPriorityQueue<TItem> : IEnumerable<TItem>
+      where TItem : GenericPriorityQueueNode {
+    private int _numNodes;
+    private TItem[] _nodes;
+    private long _numNodesEverEnqueued;
+    private readonly Comparison<TItem> _comparer;
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+    public GenericPriorityQueue(int maxNodes) : this(maxNodes, Comparer<TItem>.Default) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+    /// <param name="comparer">The comparer used to compare TPriority values.</param>
+    public GenericPriorityQueue(int maxNodes, IComparer<TItem> comparer) : this(maxNodes, comparer.Compare) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+    /// <param name="comparer">The comparison function to use to compare TPriority values</param>
+    public GenericPriorityQueue(int maxNodes, Comparison<TItem> comparer) {
+#if DEBUG
+      if (maxNodes <= 0) {
+        throw new InvalidOperationException("New queue size cannot be smaller than 1");
+      }
+#endif
+
+      _numNodes = 0;
+      _nodes = new TItem[maxNodes + 1];
+      _numNodesEverEnqueued = 0;
+      _comparer = comparer;
+    }
+
+    /// <summary>
+    /// Returns the number of nodes in the queue.
+    /// O(1)
+    /// </summary>
+    public int Count {
+      get {
+        return _numNodes;
+      }
+    }
+
+    /// <summary>
+    /// Returns the maximum number of items that can be enqueued at once in this queue.  Once you hit this number (ie. once Count == MaxSize),
+    /// attempting to enqueue another item will cause undefined behavior.  O(1)
+    /// </summary>
+    public int MaxSize {
+      get {
+        return _nodes.Length - 1;
+      }
+    }
+
+    /// <summary>
+    /// Removes every node from the queue.
+    /// O(n) (So, don't do this often!)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear() {
+      Array.Clear(_nodes, 1, _numNodes);
+      _numNodes = 0;
+    }
+
+    /// <summary>
+    /// Returns (in O(1)!) whether the given node is in the queue.  O(1)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Contains(TItem node) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (node.QueueIndex < 0 || node.QueueIndex >= _nodes.Length) {
+        throw new InvalidOperationException("node.QueueIndex has been corrupted. Did you change it manually? Or add this node to another queue?");
+      }
+#endif
+
+      return (_nodes[node.QueueIndex] == node);
+    }
+
+    /// <summary>
+    /// Enqueue a node to the priority queue.  Lower values are placed in front. Ties are broken by first-in-first-out.
+    /// If the queue is full, the result is undefined.
+    /// If the node is already enqueued, the result is undefined.
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Enqueue(TItem node) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (_numNodes >= _nodes.Length - 1) {
+        throw new InvalidOperationException("Queue is full - node cannot be added: " + node);
+      }
+      if (Contains(node)) {
+        throw new InvalidOperationException("Node is already enqueued: " + node);
+      }
+#endif
+      
+      _numNodes++;
+      _nodes[_numNodes] = node;
+      node.QueueIndex = _numNodes;
+      node.InsertionIndex = _numNodesEverEnqueued++;
+      CascadeUp(node);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void CascadeUp(TItem node) {
+      //aka Heapify-up
+      int parent;
+      if (node.QueueIndex > 1) {
+        parent = node.QueueIndex >> 1;
+        TItem parentNode = _nodes[parent];
+        if (HasHigherPriority(parentNode, node))
+          return;
+
+        //Node has lower priority value, so move parent down the heap to make room
+        _nodes[node.QueueIndex] = parentNode;
+        parentNode.QueueIndex = node.QueueIndex;
+
+        node.QueueIndex = parent;
+      } else {
+        return;
+      }
+      while (parent > 1) {
+        parent >>= 1;
+        TItem parentNode = _nodes[parent];
+        if (HasHigherPriority(parentNode, node))
+          break;
+
+        //Node has lower priority value, so move parent down the heap to make room
+        _nodes[node.QueueIndex] = parentNode;
+        parentNode.QueueIndex = node.QueueIndex;
+
+        node.QueueIndex = parent;
+      }
+      _nodes[node.QueueIndex] = node;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void CascadeDown(TItem node) {
+      //aka Heapify-down
+      int finalQueueIndex = node.QueueIndex;
+      int childLeftIndex = 2 * finalQueueIndex;
+
+      // If leaf node, we're done
+      if (childLeftIndex > _numNodes) {
+        return;
+      }
+
+      // Check if the left-child is higher-priority than the current node
+      int childRightIndex = childLeftIndex + 1;
+      TItem childLeft = _nodes[childLeftIndex];
+      if (HasHigherPriority(childLeft, node)) {
+        // Check if there is a right child. If not, swap and finish.
+        if (childRightIndex > _numNodes) {
+          node.QueueIndex = childLeftIndex;
+          childLeft.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childLeft;
+          _nodes[childLeftIndex] = node;
+          return;
+        }
+        // Check if the left-child is higher-priority than the right-child
+        TItem childRight = _nodes[childRightIndex];
+        if (HasHigherPriority(childLeft, childRight)) {
+          // left is highest, move it up and continue
+          childLeft.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childLeft;
+          finalQueueIndex = childLeftIndex;
+        } else {
+          // right is even higher, move it up and continue
+          childRight.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childRight;
+          finalQueueIndex = childRightIndex;
+        }
+      }
+      // Not swapping with left-child, does right-child exist?
+      else if (childRightIndex > _numNodes) {
+        return;
+      } else {
+        // Check if the right-child is higher-priority than the current node
+        TItem childRight = _nodes[childRightIndex];
+        if (HasHigherPriority(childRight, node)) {
+          childRight.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = childRight;
+          finalQueueIndex = childRightIndex;
+        }
+        // Neither child is higher-priority than current, so finish and stop.
+        else {
+          return;
+        }
+      }
+
+      while (true) {
+        childLeftIndex = 2 * finalQueueIndex;
+
+        // If leaf node, we're done
+        if (childLeftIndex > _numNodes) {
+          node.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = node;
+          break;
+        }
+
+        // Check if the left-child is higher-priority than the current node
+        childRightIndex = childLeftIndex + 1;
+        childLeft = _nodes[childLeftIndex];
+        if (HasHigherPriority(childLeft, node)) {
+          // Check if there is a right child. If not, swap and finish.
+          if (childRightIndex > _numNodes) {
+            node.QueueIndex = childLeftIndex;
+            childLeft.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childLeft;
+            _nodes[childLeftIndex] = node;
+            break;
+          }
+          // Check if the left-child is higher-priority than the right-child
+          TItem childRight = _nodes[childRightIndex];
+          if (HasHigherPriority(childLeft, childRight)) {
+            // left is highest, move it up and continue
+            childLeft.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childLeft;
+            finalQueueIndex = childLeftIndex;
+          } else {
+            // right is even higher, move it up and continue
+            childRight.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childRight;
+            finalQueueIndex = childRightIndex;
+          }
+        }
+        // Not swapping with left-child, does right-child exist?
+        else if (childRightIndex > _numNodes) {
+          node.QueueIndex = finalQueueIndex;
+          _nodes[finalQueueIndex] = node;
+          break;
+        } else {
+          // Check if the right-child is higher-priority than the current node
+          TItem childRight = _nodes[childRightIndex];
+          if (HasHigherPriority(childRight, node)) {
+            childRight.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = childRight;
+            finalQueueIndex = childRightIndex;
+          }
+          // Neither child is higher-priority than current, so finish and stop.
+          else {
+            node.QueueIndex = finalQueueIndex;
+            _nodes[finalQueueIndex] = node;
+            break;
+          }
+        }
+      }
+    }
+
+    /// <summary>
+    /// Returns true if 'higher' has higher priority than 'lower', false otherwise.
+    /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private bool HasHigherPriority(TItem higher, TItem lower) {
+      var cmp = _comparer(higher, lower);
+      return (cmp < 0 || (cmp == 0 && higher.InsertionIndex < lower.InsertionIndex));
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+    /// If queue is empty, result is undefined
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public TItem Dequeue() {
+#if DEBUG
+      if (_numNodes <= 0) {
+        throw new InvalidOperationException("Cannot call Dequeue() on an empty queue");
+      }
+
+      if (!IsValidQueue()) {
+        throw new InvalidOperationException("Queue has been corrupted (Did you update a node priority manually instead of calling UpdatePriority()?" +
+                                            "Or add the same node to two different queues?)");
+      }
+#endif
+
+      TItem returnMe = _nodes[1];
+      //If the node is already the last node, we can remove it immediately
+      if (_numNodes == 1) {
+        _nodes[1] = null;
+        _numNodes = 0;
+        return returnMe;
+      }
+
+      //Swap the node with the last node
+      TItem formerLastNode = _nodes[_numNodes];
+      _nodes[1] = formerLastNode;
+      formerLastNode.QueueIndex = 1;
+      _nodes[_numNodes] = null;
+      _numNodes--;
+
+      //Now bubble formerLastNode (which is no longer the last node) down
+      CascadeDown(formerLastNode);
+      return returnMe;
+    }
+
+    /// <summary>
+    /// Resize the queue so it can accept more nodes.  All currently enqueued nodes are remain.
+    /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior
+    /// O(n)
+    /// </summary>
+    public void Resize(int maxNodes) {
+#if DEBUG
+      if (maxNodes <= 0) {
+        throw new InvalidOperationException("Queue size cannot be smaller than 1");
+      }
+
+      if (maxNodes < _numNodes) {
+        throw new InvalidOperationException("Called Resize(" + maxNodes + "), but current queue contains " + _numNodes + " nodes");
+      }
+#endif
+
+      TItem[] newArray = new TItem[maxNodes + 1];
+      int highestIndexToCopy = Math.Min(maxNodes, _numNodes);
+      Array.Copy(_nodes, newArray, highestIndexToCopy + 1);
+      _nodes = newArray;
+    }
+
+    /// <summary>
+    /// Returns the head of the queue, without removing it (use Dequeue() for that).
+    /// If the queue is empty, behavior is undefined.
+    /// O(1)
+    /// </summary>
+    public TItem First {
+      get {
+#if DEBUG
+        if (_numNodes <= 0) {
+          throw new InvalidOperationException("Cannot call .First on an empty queue");
+        }
+#endif
+
+        return _nodes[1];
+      }
+    }
+
+    /// <summary>
+    /// This method must be called on a node every time its priority changes while it is in the queue.  
+    /// <b>Forgetting to call this method will result in a corrupted queue!</b>
+    /// Calling this method on a node not in the queue results in undefined behavior
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void UpdatePriority(TItem node) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (!Contains(node)) {
+        throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + node);
+      }
+#endif
+      
+      OnNodeUpdated(node);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private void OnNodeUpdated(TItem node) {
+      //Bubble the updated node up or down as appropriate
+      int parentIndex = node.QueueIndex >> 1;
+
+      if (parentIndex > 0 && HasHigherPriority(node, _nodes[parentIndex])) {
+        CascadeUp(node);
+      } else {
+        //Note that CascadeDown will be called if parentNode == node (that is, node is the root)
+        CascadeDown(node);
+      }
+    }
+
+    /// <summary>
+    /// Removes a node from the queue.  The node does not need to be the head of the queue.  
+    /// If the node is not in the queue, the result is undefined.  If unsure, check Contains() first
+    /// O(log n)
+    /// </summary>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Remove(TItem node) {
+#if DEBUG
+      if (node == null) {
+        throw new ArgumentNullException("node");
+      }
+      if (!Contains(node)) {
+        throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + node);
+      }
+#endif
+
+      //If the node is already the last node, we can remove it immediately
+      if (node.QueueIndex == _numNodes) {
+        _nodes[_numNodes] = null;
+        _numNodes--;
+        return;
+      }
+
+      //Swap the node with the last node
+      TItem formerLastNode = _nodes[_numNodes];
+      _nodes[node.QueueIndex] = formerLastNode;
+      formerLastNode.QueueIndex = node.QueueIndex;
+      _nodes[_numNodes] = null;
+      _numNodes--;
+
+      //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate
+      OnNodeUpdated(formerLastNode);
+    }
+
+    public IEnumerator<TItem> GetEnumerator() {
+      IEnumerable<TItem> e = new ArraySegment<TItem>(_nodes, 1, _numNodes);
+      return e.GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator() {
+      return GetEnumerator();
+    }
+
+    /// <summary>
+    /// <b>Should not be called in production code.</b>
+    /// Checks to make sure the queue is still in a valid state.  Used for testing/debugging the queue.
+    /// </summary>
+    public bool IsValidQueue() {
+      for (int i = 1; i < _nodes.Length; i++) {
+        if (_nodes[i] != null) {
+          int childLeftIndex = 2 * i;
+          if (childLeftIndex < _nodes.Length && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i]))
+            return false;
+
+          int childRightIndex = childLeftIndex + 1;
+          if (childRightIndex < _nodes.Length && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i]))
+            return false;
+        }
+      }
+      return true;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/GenericPriorityQueueNode.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/GenericPriorityQueueNode.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/GenericPriorityQueueNode.cs	(revision 16892)
@@ -0,0 +1,58 @@
+﻿#region License
+/*
+The MIT License (MIT)
+
+Copyright (c) 2013 Daniel "BlueRaja" Pflughoeft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+#endregion
+
+namespace SimSharp {
+
+  /// <summary>
+  /// A node class for the generic priority queue
+  /// </summary>
+  public class GenericPriorityQueueNode {
+    /// <summary>
+    /// Represents the current position in the queue
+    /// </summary>
+    public int QueueIndex { get; internal set; }
+
+    /// <summary>
+    /// Represents the order the node was inserted in
+    /// </summary>
+    public long InsertionIndex { get; internal set; }
+  }
+
+  /// <summary>
+  /// A node class for the generic priority queue with an explicit priority type
+  /// </summary>
+  /// <remarks>
+  /// Original sources from https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+  /// </remarks>
+  /// <typeparam name="TPriority"></typeparam>
+  public class GenericPriorityQueueNode<TPriority> : GenericPriorityQueueNode {
+    /// <summary>
+    /// The Priority to insert this node at.  Must be set BEFORE adding a node to the queue (ideally just once, in the node's constructor).
+    /// Should not be manually edited once the node has been enqueued - use queue.UpdatePriority() instead
+    /// </summary>
+    public TPriority Priority { get; protected internal set; }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/ReverseComparer.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/ReverseComparer.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/ReverseComparer.cs	(revision 16892)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  public class ReverseComparer<T> : IComparer<T> where T : IComparable {
+    private static readonly IComparer<T> DefaultComparer = Comparer<T>.Default;
+
+    public int Compare(T x, T y) {
+      return DefaultComparer.Compare(y, x);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/SimplePriorityQueue.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/SimplePriorityQueue.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/SimplePriorityQueue.cs	(revision 16892)
@@ -0,0 +1,837 @@
+﻿#region License
+/*
+The MIT License (MIT)
+
+Copyright (c) 2013 Daniel "BlueRaja" Pflughoeft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SimSharp {
+  /// <summary>
+  /// A simplified priority queue implementation.  Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than
+  /// FastPriorityQueue
+  /// Methods tagged as O(1) or O(log n) are assuming there are no duplicates.  Duplicates may increase the algorithmic complexity.
+  /// </summary>
+  /// <remarks>
+  /// Original sources from https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+  /// </remarks>
+  /// <typeparam name="TItem">The type to enqueue</typeparam>
+  /// <typeparam name="TPriority">The priority-type to use for nodes.  Must extend IComparable&lt;TPriority&gt;</typeparam>
+  public class SimplePriorityQueue<TItem, TPriority> : IEnumerable<TItem>
+      where TPriority : IComparable<TPriority> {
+    private class SimpleNode : GenericPriorityQueueNode<TPriority> {
+      public TItem Data { get; private set; }
+
+      public SimpleNode(TItem data) {
+        Data = data;
+      }
+    }
+
+    private const int INITIAL_QUEUE_SIZE = 64;
+    private readonly GenericPriorityQueue<SimpleNode, TPriority> _queue;
+    private readonly Dictionary<TItem, IList<SimpleNode>> _itemToNodesCache;
+    private readonly IList<SimpleNode> _nullNodesCache;
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    public SimplePriorityQueue() : this(Comparer<TPriority>.Default) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="comparer">The comparer used to compare TPriority values.  Defaults to Comparer&lt;TPriority&gt;.default</param>
+    public SimplePriorityQueue(IComparer<TPriority> comparer) : this(comparer.Compare) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="comparer">The comparison function to use to compare TPriority values</param>
+    public SimplePriorityQueue(Comparison<TPriority> comparer) {
+      _queue = new GenericPriorityQueue<SimpleNode, TPriority>(INITIAL_QUEUE_SIZE, comparer);
+      _itemToNodesCache = new Dictionary<TItem, IList<SimpleNode>>();
+      _nullNodesCache = new List<SimpleNode>();
+    }
+
+    /// <summary>
+    /// Given an item of type T, returns the exist SimpleNode in the queue
+    /// </summary>
+    private SimpleNode GetExistingNode(TItem item) {
+      if (item == null) {
+        return _nullNodesCache.Count > 0 ? _nullNodesCache[0] : null;
+      }
+
+      IList<SimpleNode> nodes;
+      if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+        return null;
+      }
+      return nodes[0];
+    }
+
+    /// <summary>
+    /// Adds an item to the Node-cache to allow for many methods to be O(1) or O(log n)
+    /// </summary>
+    private void AddToNodeCache(SimpleNode node) {
+      if (node.Data == null) {
+        _nullNodesCache.Add(node);
+        return;
+      }
+
+      IList<SimpleNode> nodes;
+      if (!_itemToNodesCache.TryGetValue(node.Data, out nodes)) {
+        nodes = new List<SimpleNode>();
+        _itemToNodesCache[node.Data] = nodes;
+      }
+      nodes.Add(node);
+    }
+
+    /// <summary>
+    /// Removes an item to the Node-cache to allow for many methods to be O(1) or O(log n) (assuming no duplicates)
+    /// </summary>
+    private void RemoveFromNodeCache(SimpleNode node) {
+      if (node.Data == null) {
+        _nullNodesCache.Remove(node);
+        return;
+      }
+
+      IList<SimpleNode> nodes;
+      if (!_itemToNodesCache.TryGetValue(node.Data, out nodes)) {
+        return;
+      }
+      nodes.Remove(node);
+      if (nodes.Count == 0) {
+        _itemToNodesCache.Remove(node.Data);
+      }
+    }
+
+    /// <summary>
+    /// Returns the number of nodes in the queue.
+    /// O(1)
+    /// </summary>
+    public int Count {
+      get {
+        return _queue.Count;
+      }
+    }
+
+
+    /// <summary>
+    /// Returns the head of the queue, without removing it (use Dequeue() for that).
+    /// Throws an exception when the queue is empty.
+    /// O(1)
+    /// </summary>
+    public TItem First {
+      get {
+        if (_queue.Count <= 0) {
+          throw new InvalidOperationException("Cannot call .First on an empty queue");
+        }
+
+        return _queue.First.Data;
+      }
+    }
+
+    /// <summary>
+    /// Returns the top priority of the queue.
+    /// Throws an exception when the queue is empty.
+    /// O(1)
+    /// </summary>
+    public TPriority Peek {
+      get {
+        lock (_queue) {
+          if (_queue.Count <= 0) {
+            throw new InvalidOperationException("Cannot call .Peek on an empty queue");
+          }
+          return _queue.First.Priority;
+        }
+      }
+    }
+
+    /// <summary>
+    /// Removes every node from the queue.
+    /// O(n)
+    /// </summary>
+    public void Clear() {
+      _queue.Clear();
+      _itemToNodesCache.Clear();
+      _nullNodesCache.Clear();
+    }
+
+    /// <summary>
+    /// Returns whether the given item is in the queue.
+    /// O(1)
+    /// </summary>
+    public bool Contains(TItem item) {
+      if (item == null) {
+        return _nullNodesCache.Count > 0;
+      }
+      return _itemToNodesCache.ContainsKey(item);
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+    /// If queue is empty, throws an exception
+    /// O(log n)
+    /// </summary>
+    public TItem Dequeue() {
+      if (_queue.Count <= 0) {
+        throw new InvalidOperationException("Cannot call Dequeue() on an empty queue");
+      }
+
+      SimpleNode node = _queue.Dequeue();
+      RemoveFromNodeCache(node);
+      return node.Data;
+    }
+
+    /// <summary>
+    /// Enqueue the item with the given priority, without calling AddToNodeCache(node)
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="priority"></param>
+    /// <returns></returns>
+    private SimpleNode EnqueueNoCache(TItem item, TPriority priority) {
+      SimpleNode node = new SimpleNode(item);
+      if (_queue.Count == _queue.MaxSize) {
+        _queue.Resize(_queue.MaxSize * 2 + 1);
+      }
+      _queue.Enqueue(node, priority);
+      return node;
+    }
+
+    /// <summary>
+    /// Enqueue a node to the priority queue.  Lower values are placed in front. Ties are broken by first-in-first-out.
+    /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'.
+    /// Duplicates and null-values are allowed.
+    /// O(log n)
+    /// </summary>
+    public void Enqueue(TItem item, TPriority priority) {
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        nodes = _nullNodesCache;
+      } else if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+        nodes = new List<SimpleNode>();
+        _itemToNodesCache[item] = nodes;
+      }
+      SimpleNode node = EnqueueNoCache(item, priority);
+      nodes.Add(node);
+    }
+
+    /// <summary>
+    /// Enqueue a node to the priority queue if it doesn't already exist.  Lower values are placed in front. Ties are broken by first-in-first-out.
+    /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'.  Null values are allowed.
+    /// Returns true if the node was successfully enqueued; false if it already exists.
+    /// O(log n)
+    /// </summary>
+    public bool EnqueueWithoutDuplicates(TItem item, TPriority priority) {
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        if (_nullNodesCache.Count > 0) {
+          return false;
+        }
+        nodes = _nullNodesCache;
+      } else if (_itemToNodesCache.ContainsKey(item)) {
+        return false;
+      } else {
+        nodes = new List<SimpleNode>();
+        _itemToNodesCache[item] = nodes;
+      }
+      SimpleNode node = EnqueueNoCache(item, priority);
+      nodes.Add(node);
+      return true;
+    }
+
+    /// <summary>
+    /// Removes an item from the queue.  The item does not need to be the head of the queue.  
+    /// If the item is not in the queue, an exception is thrown.  If unsure, check Contains() first.
+    /// If multiple copies of the item are enqueued, only the first one is removed. 
+    /// O(log n)
+    /// </summary>
+    public void Remove(TItem item) {
+      SimpleNode removeMe;
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        if (_nullNodesCache.Count == 0) {
+          throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item);
+        }
+        removeMe = _nullNodesCache[0];
+        nodes = _nullNodesCache;
+      } else {
+        if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+          throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item);
+        }
+        removeMe = nodes[0];
+        if (nodes.Count == 1) {
+          _itemToNodesCache.Remove(item);
+        }
+      }
+      _queue.Remove(removeMe);
+      nodes.Remove(removeMe);
+    }
+
+    /// <summary>
+    /// Call this method to change the priority of an item.
+    /// Calling this method on a item not in the queue will throw an exception.
+    /// If the item is enqueued multiple times, only the first one will be updated.
+    /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+    /// to update all of them, please wrap your items in a wrapper class so they can be distinguished).
+    /// O(log n)
+    /// </summary>
+    public void UpdatePriority(TItem item, TPriority priority) {
+      SimpleNode updateMe = GetExistingNode(item);
+      if (updateMe == null) {
+        throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item);
+      }
+      _queue.UpdatePriority(updateMe, priority);
+    }
+
+    /// <summary>
+    /// Returns the priority of the given item.
+    /// Calling this method on a item not in the queue will throw an exception.
+    /// If the item is enqueued multiple times, only the priority of the first will be returned.
+    /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+    /// to query all their priorities, please wrap your items in a wrapper class so they can be distinguished).
+    /// O(1)
+    /// </summary>
+    public TPriority GetPriority(TItem item) {
+      SimpleNode findMe = GetExistingNode(item);
+      if (findMe == null) {
+        throw new InvalidOperationException("Cannot call GetPriority() on a node which is not enqueued: " + item);
+      }
+      return findMe.Priority;
+    }
+
+    #region Try* methods for multithreading
+    /// Get the head of the queue, without removing it (use TryDequeue() for that).
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and First
+    /// Returns true if successful, false otherwise
+    /// O(1)
+    public bool TryFirst(out TItem first) {
+      if (_queue.Count <= 0) {
+        first = default(TItem);
+        return false;
+      }
+
+      first = _queue.First.Data;
+      return true;
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and sets it to first.
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and Dequeue()
+    /// Returns true if successful; false if queue was empty
+    /// O(log n)
+    /// </summary>
+    public bool TryDequeue(out TItem first) {
+      if (_queue.Count <= 0) {
+        first = default(TItem);
+        return false;
+      }
+
+      SimpleNode node = _queue.Dequeue();
+      first = node.Data;
+      RemoveFromNodeCache(node);
+      return true;
+    }
+
+    /// <summary>
+    /// Attempts to remove an item from the queue.  The item does not need to be the head of the queue.  
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and Remove()
+    /// Returns true if the item was successfully removed, false if it wasn't in the queue.
+    /// If multiple copies of the item are enqueued, only the first one is removed. 
+    /// O(log n)
+    /// </summary>
+    public bool TryRemove(TItem item) {
+      SimpleNode removeMe;
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        if (_nullNodesCache.Count == 0) {
+          return false;
+        }
+        removeMe = _nullNodesCache[0];
+        nodes = _nullNodesCache;
+      } else {
+        if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+          return false;
+        }
+        removeMe = nodes[0];
+        if (nodes.Count == 1) {
+          _itemToNodesCache.Remove(item);
+        }
+      }
+      _queue.Remove(removeMe);
+      nodes.Remove(removeMe);
+      return true;
+    }
+
+    /// <summary>
+    /// Call this method to change the priority of an item.
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and UpdatePriority()
+    /// If the item is enqueued multiple times, only the first one will be updated.
+    /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+    /// to update all of them, please wrap your items in a wrapper class so they can be distinguished).
+    /// Returns true if the item priority was updated, false otherwise.
+    /// O(log n)
+    /// </summary>
+    public bool TryUpdatePriority(TItem item, TPriority priority) {
+      SimpleNode updateMe = GetExistingNode(item);
+      if (updateMe == null) {
+        return false;
+      }
+      _queue.UpdatePriority(updateMe, priority);
+      return true;
+    }
+
+    /// <summary>
+    /// Attempt to get the priority of the given item.
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and GetPriority()
+    /// If the item is enqueued multiple times, only the priority of the first will be returned.
+    /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+    /// to query all their priorities, please wrap your items in a wrapper class so they can be distinguished).
+    /// Returns true if the item was found in the queue, false otherwise
+    /// O(1)
+    /// </summary>
+    public bool TryGetPriority(TItem item, out TPriority priority) {
+      SimpleNode findMe = GetExistingNode(item);
+      if (findMe == null) {
+        priority = default(TPriority);
+        return false;
+      }
+      priority = findMe.Priority;
+      return true;
+    }
+    #endregion
+
+    public IEnumerator<TItem> GetEnumerator() {
+      return _queue.Select(x => x.Data).GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator() {
+      return GetEnumerator();
+    }
+
+    public bool IsValidQueue() {
+      // Check all items in cache are in the queue
+      foreach (IList<SimpleNode> nodes in _itemToNodesCache.Values) {
+        foreach (SimpleNode node in nodes) {
+          if (!_queue.Contains(node)) {
+            return false;
+          }
+        }
+      }
+
+      // Check all items in queue are in cache
+      foreach (SimpleNode node in _queue) {
+        if (GetExistingNode(node.Data) == null) {
+          return false;
+        }
+      }
+
+      // Check queue structure itself
+      return _queue.IsValidQueue();
+    }
+  }
+
+  /// <summary>
+  /// A simplified priority queue implementation.  Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than
+  /// FastPriorityQueue
+  /// Methods tagged as O(1) or O(log n) are assuming there are no duplicates.  Duplicates may increase the algorithmic complexity.
+  /// </summary>
+  /// <typeparam name="TItem">The type to enqueue</typeparam>
+  public class SimplePriorityQueue<TItem> : IEnumerable<TItem> where TItem : IComparable<TItem> {
+    private class SimpleNode : GenericPriorityQueueNode, IComparable<SimpleNode>, IComparable {
+      public TItem Data { get; private set; }
+      private Comparison<TItem> _comparer;
+
+      public SimpleNode(TItem data, Comparison<TItem> comparer) {
+        Data = data;
+        _comparer = comparer;
+      }
+
+      public int CompareTo(SimpleNode other) {
+        if (other == null) return 1;
+        return _comparer(Data, other.Data);
+      }
+
+      public int CompareTo(object obj) {
+        if (obj is SimpleNode other) return CompareTo(other);
+        if (obj == null) return 1;
+        throw new ArgumentException("can only compare to objects of type SimpleNode.");
+      }
+    }
+
+    private const int INITIAL_QUEUE_SIZE = 64;
+    private readonly GenericPriorityQueue<SimpleNode> _queue;
+    private readonly Dictionary<TItem, IList<SimpleNode>> _itemToNodesCache;
+    private readonly IList<SimpleNode> _nullNodesCache;
+    private readonly Comparison<TItem> _comparer;
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    public SimplePriorityQueue() : this(Comparer<TItem>.Default) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="comparer">The comparer used to compare TPriority values.  Defaults to Comparer&lt;TPriority&gt;.default</param>
+    public SimplePriorityQueue(IComparer<TItem> comparer) : this(comparer.Compare) { }
+
+    /// <summary>
+    /// Instantiate a new Priority Queue
+    /// </summary>
+    /// <param name="comparer">The comparison function to use to compare TPriority values</param>
+    public SimplePriorityQueue(Comparison<TItem> comparer) {
+      _comparer = comparer;
+      // the inner priority queue will always use the default comparer which in turn makes use of the specified comparer
+      _queue = new GenericPriorityQueue<SimpleNode>(INITIAL_QUEUE_SIZE, Comparer<SimpleNode>.Default);
+      _itemToNodesCache = new Dictionary<TItem, IList<SimpleNode>>();
+      _nullNodesCache = new List<SimpleNode>();
+    }
+
+    /// <summary>
+    /// Given an item of type T, returns the exist SimpleNode in the queue
+    /// </summary>
+    private SimpleNode GetExistingNode(TItem item) {
+      if (item == null) {
+        return _nullNodesCache.Count > 0 ? _nullNodesCache[0] : null;
+      }
+
+      IList<SimpleNode> nodes;
+      if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+        return null;
+      }
+      return nodes[0];
+    }
+
+    /// <summary>
+    /// Adds an item to the Node-cache to allow for many methods to be O(1) or O(log n)
+    /// </summary>
+    private void AddToNodeCache(SimpleNode node) {
+      if (node.Data == null) {
+        _nullNodesCache.Add(node);
+        return;
+      }
+
+      IList<SimpleNode> nodes;
+      if (!_itemToNodesCache.TryGetValue(node.Data, out nodes)) {
+        nodes = new List<SimpleNode>();
+        _itemToNodesCache[node.Data] = nodes;
+      }
+      nodes.Add(node);
+    }
+
+    /// <summary>
+    /// Removes an item to the Node-cache to allow for many methods to be O(1) or O(log n) (assuming no duplicates)
+    /// </summary>
+    private void RemoveFromNodeCache(SimpleNode node) {
+      if (node.Data == null) {
+        _nullNodesCache.Remove(node);
+        return;
+      }
+
+      IList<SimpleNode> nodes;
+      if (!_itemToNodesCache.TryGetValue(node.Data, out nodes)) {
+        return;
+      }
+      nodes.Remove(node);
+      if (nodes.Count == 0) {
+        _itemToNodesCache.Remove(node.Data);
+      }
+    }
+
+    /// <summary>
+    /// Returns the number of nodes in the queue.
+    /// O(1)
+    /// </summary>
+    public int Count {
+      get {
+        return _queue.Count;
+      }
+    }
+
+
+    /// <summary>
+    /// Returns the head of the queue, without removing it (use Dequeue() for that).
+    /// Throws an exception when the queue is empty.
+    /// O(1)
+    /// </summary>
+    public TItem First {
+      get {
+        if (_queue.Count <= 0) {
+          throw new InvalidOperationException("Cannot call .First on an empty queue");
+        }
+
+        return _queue.First.Data;
+      }
+    }
+
+    /// <summary>
+    /// Removes every node from the queue.
+    /// O(n)
+    /// </summary>
+    public void Clear() {
+      _queue.Clear();
+      _itemToNodesCache.Clear();
+      _nullNodesCache.Clear();
+    }
+
+    /// <summary>
+    /// Returns whether the given item is in the queue.
+    /// O(1)
+    /// </summary>
+    public bool Contains(TItem item) {
+      if (item == null) {
+        return _nullNodesCache.Count > 0;
+      }
+      return _itemToNodesCache.ContainsKey(item);
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+    /// If queue is empty, throws an exception
+    /// O(log n)
+    /// </summary>
+    public TItem Dequeue() {
+      if (_queue.Count <= 0) {
+        throw new InvalidOperationException("Cannot call Dequeue() on an empty queue");
+      }
+
+      SimpleNode node = _queue.Dequeue();
+      RemoveFromNodeCache(node);
+      return node.Data;
+    }
+
+    /// <summary>
+    /// Enqueue the item with the given priority, without calling AddToNodeCache(node)
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    private SimpleNode EnqueueNoCache(TItem item) {
+      SimpleNode node = new SimpleNode(item, _comparer);
+      if (_queue.Count == _queue.MaxSize) {
+        _queue.Resize(_queue.MaxSize * 2 + 1);
+      }
+      _queue.Enqueue(node);
+      return node;
+    }
+
+    /// <summary>
+    /// Enqueue a node to the priority queue.  Lower values are placed in front. Ties are broken by first-in-first-out.
+    /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'.
+    /// Duplicates and null-values are allowed.
+    /// O(log n)
+    /// </summary>
+    public void Enqueue(TItem item) {
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        nodes = _nullNodesCache;
+      } else if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+        nodes = new List<SimpleNode>();
+        _itemToNodesCache[item] = nodes;
+      }
+      SimpleNode node = EnqueueNoCache(item);
+      nodes.Add(node);
+    }
+
+    /// <summary>
+    /// Enqueue a node to the priority queue if it doesn't already exist.  Lower values are placed in front. Ties are broken by first-in-first-out.
+    /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'.  Null values are allowed.
+    /// Returns true if the node was successfully enqueued; false if it already exists.
+    /// O(log n)
+    /// </summary>
+    public bool EnqueueWithoutDuplicates(TItem item) {
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        if (_nullNodesCache.Count > 0) {
+          return false;
+        }
+        nodes = _nullNodesCache;
+      } else if (_itemToNodesCache.ContainsKey(item)) {
+        return false;
+      } else {
+        nodes = new List<SimpleNode>();
+        _itemToNodesCache[item] = nodes;
+      }
+      SimpleNode node = EnqueueNoCache(item);
+      nodes.Add(node);
+      return true;
+    }
+
+    /// <summary>
+    /// Removes an item from the queue.  The item does not need to be the head of the queue.  
+    /// If the item is not in the queue, an exception is thrown.  If unsure, check Contains() first.
+    /// If multiple copies of the item are enqueued, only the first one is removed. 
+    /// O(log n)
+    /// </summary>
+    public void Remove(TItem item) {
+      SimpleNode removeMe;
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        if (_nullNodesCache.Count == 0) {
+          throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item);
+        }
+        removeMe = _nullNodesCache[0];
+        nodes = _nullNodesCache;
+      } else {
+        if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+          throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item);
+        }
+        removeMe = nodes[0];
+        if (nodes.Count == 1) {
+          _itemToNodesCache.Remove(item);
+        }
+      }
+      _queue.Remove(removeMe);
+      nodes.Remove(removeMe);
+    }
+
+    /// <summary>
+    /// Call this method to change the priority of an item.
+    /// Calling this method on a item not in the queue will throw an exception.
+    /// If the item is enqueued multiple times, only the first one will be updated.
+    /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+    /// to update all of them, please wrap your items in a wrapper class so they can be distinguished).
+    /// O(log n)
+    /// </summary>
+    public void UpdatePriority(TItem item) {
+      SimpleNode updateMe = GetExistingNode(item);
+      if (updateMe == null) {
+        throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item);
+      }
+      _queue.UpdatePriority(updateMe);
+    }
+
+    #region Try* methods for multithreading
+    /// Get the head of the queue, without removing it (use TryDequeue() for that).
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and First
+    /// Returns true if successful, false otherwise
+    /// O(1)
+    public bool TryFirst(out TItem first) {
+      if (_queue.Count <= 0) {
+        first = default(TItem);
+        return false;
+      }
+
+      first = _queue.First.Data;
+      return true;
+    }
+
+    /// <summary>
+    /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and sets it to first.
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and Dequeue()
+    /// Returns true if successful; false if queue was empty
+    /// O(log n)
+    /// </summary>
+    public bool TryDequeue(out TItem first) {
+      if (_queue.Count <= 0) {
+        first = default(TItem);
+        return false;
+      }
+
+      SimpleNode node = _queue.Dequeue();
+      first = node.Data;
+      RemoveFromNodeCache(node);
+      return true;
+    }
+
+    /// <summary>
+    /// Attempts to remove an item from the queue.  The item does not need to be the head of the queue.  
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and Remove()
+    /// Returns true if the item was successfully removed, false if it wasn't in the queue.
+    /// If multiple copies of the item are enqueued, only the first one is removed. 
+    /// O(log n)
+    /// </summary>
+    public bool TryRemove(TItem item) {
+      SimpleNode removeMe;
+      IList<SimpleNode> nodes;
+      if (item == null) {
+        if (_nullNodesCache.Count == 0) {
+          return false;
+        }
+        removeMe = _nullNodesCache[0];
+        nodes = _nullNodesCache;
+      } else {
+        if (!_itemToNodesCache.TryGetValue(item, out nodes)) {
+          return false;
+        }
+        removeMe = nodes[0];
+        if (nodes.Count == 1) {
+          _itemToNodesCache.Remove(item);
+        }
+      }
+      _queue.Remove(removeMe);
+      nodes.Remove(removeMe);
+      return true;
+    }
+
+    /// <summary>
+    /// Call this method to change the priority of an item.
+    /// Useful for multi-threading, where the queue may become empty between calls to Contains() and UpdatePriority()
+    /// If the item is enqueued multiple times, only the first one will be updated.
+    /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+    /// to update all of them, please wrap your items in a wrapper class so they can be distinguished).
+    /// Returns true if the item priority was updated, false otherwise.
+    /// O(log n)
+    /// </summary>
+    public bool TryUpdatePriority(TItem item) {
+      SimpleNode updateMe = GetExistingNode(item);
+      if (updateMe == null) {
+        return false;
+      }
+      _queue.UpdatePriority(updateMe);
+      return true;
+    }
+    #endregion
+
+    public IEnumerator<TItem> GetEnumerator() {
+      return _queue.Select(x => x.Data).GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator() {
+      return GetEnumerator();
+    }
+
+    public bool IsValidQueue() {
+      // Check all items in cache are in the queue
+      foreach (IList<SimpleNode> nodes in _itemToNodesCache.Values) {
+        foreach (SimpleNode node in nodes) {
+          if (!_queue.Contains(node)) {
+            return false;
+          }
+        }
+      }
+
+      // Check all items in queue are in cache
+      foreach (SimpleNode node in _queue) {
+        if (GetExistingNode(node.Data) == null) {
+          return false;
+        }
+      }
+
+      // Check queue structure itself
+      return _queue.IsValidQueue();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/ActiveObject.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/ActiveObject.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/ActiveObject.cs	(revision 16892)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+namespace SimSharp {
+  public abstract class ActiveObject<T> where T : Simulation {
+    protected T Environment { get; private set; }
+
+    protected ActiveObject(T environment) {
+      Environment = environment;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Environment.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Environment.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Environment.cs	(revision 16892)
@@ -0,0 +1,888 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace SimSharp {
+  /// <summary>
+  /// Simulation hold the event queues, schedule and process events.
+  /// </summary>
+  /// <remarks>
+  /// This class is not thread-safe against manipulation of the event queue. If you supply a termination
+  /// event that is set outside the simulation, please use the <see cref="ThreadSafeSimulation"/> environment.
+  /// 
+  /// For most purposes <see cref="Simulation"/> is however the better and faster choice.
+  /// </remarks>
+  public class Simulation {
+    private const int InitialMaxEvents = 1024;
+
+    /// <summary>
+    /// Describes the number of seconds that a logical step of 1 in the *D-API takes.
+    /// </summary>
+    protected double DefaultTimeStepSeconds { get; private set; }
+
+    /// <summary>
+    /// Calculates the logical date of the simulation by the amount of default steps
+    /// that have passed.
+    /// </summary>
+    public double NowD {
+      get { return (Now - StartDate).TotalSeconds / DefaultTimeStepSeconds; }
+    }
+
+    /// <summary>
+    /// The current simulation time as a calendar date.
+    /// </summary>
+    public DateTime Now { get; protected set; }
+
+    /// <summary>
+    /// The calendar date when the simulation started. This defaults to 1970-1-1 if
+    /// no other date has been specified in the overloaded constructor.
+    /// </summary>
+    public DateTime StartDate { get; protected set; }
+
+    /// <summary>
+    /// The random number generator that is to be used in all events in
+    /// order to produce reproducible results.
+    /// </summary>
+    protected IRandom Random { get; set; }
+
+    protected EventQueue ScheduleQ;
+    public Process ActiveProcess { get; set; }
+
+    public TextWriter Logger { get; set; }
+    public int ProcessedEvents { get; protected set; }
+
+    public Simulation() : this(new DateTime(1970, 1, 1)) { }
+    public Simulation(TimeSpan? defaultStep) : this(new DateTime(1970, 1, 1), defaultStep) { }
+    public Simulation(int randomSeed, TimeSpan? defaultStep = null) : this(new DateTime(1970, 1, 1), randomSeed, defaultStep) { }
+    public Simulation(DateTime initialDateTime, TimeSpan? defaultStep = null) : this(new PcgRandom(), initialDateTime, defaultStep) { }
+    public Simulation(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null) : this(new PcgRandom(randomSeed), initialDateTime, defaultStep) { }
+    public Simulation(IRandom random, DateTime initialDateTime, TimeSpan? defaultStep = null) {
+      DefaultTimeStepSeconds = (defaultStep ?? TimeSpan.FromSeconds(1)).Duration().TotalSeconds;
+      StartDate = initialDateTime;
+      Now = initialDateTime;
+      Random = random;
+      ScheduleQ = new EventQueue(InitialMaxEvents);
+      Logger = Console.Out;
+    }
+
+    public double ToDouble(TimeSpan span) {
+      return span.TotalSeconds / DefaultTimeStepSeconds;
+    }
+
+    public TimeSpan ToTimeSpan(double span) {
+      return TimeSpan.FromSeconds(DefaultTimeStepSeconds * span);
+    }
+
+    /// <summary>
+    /// Creates a new process from an event generator. The process is automatically
+    /// scheduled to be started at the current simulation time.
+    /// </summary>
+    /// <param name="generator">The generator function that represents the process.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    /// <returns>The scheduled process that was created.</returns>
+    public Process Process(IEnumerable<Event> generator, int priority = 0) {
+      return new Process(this, generator, priority);
+    }
+
+    /// <summary>
+    /// Creates and returns a new timeout.
+    /// </summary>
+    /// <param name="delay">The time after which the timeout is fired.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    /// <returns>The scheduled timeout event that was created.</returns>
+    public Timeout TimeoutD(double delay, int priority = 0) {
+      return Timeout(TimeSpan.FromSeconds(DefaultTimeStepSeconds * delay), priority);
+    }
+
+    /// <summary>
+    /// Creates and returns a new timeout.
+    /// </summary>
+    /// <param name="delay">The time after which the timeout is fired.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    /// <returns>The scheduled timeout event that was created.</returns>
+    public Timeout Timeout(TimeSpan delay, int priority = 0) {
+      return new Timeout(this, delay, priority: priority);
+    }
+
+    public virtual void Reset(int randomSeed) {
+      ProcessedEvents = 0;
+      Now = StartDate;
+      Random = new PcgRandom(randomSeed);
+      ScheduleQ = new EventQueue(InitialMaxEvents);
+      useSpareNormal = false;
+    }
+
+    public virtual void ScheduleD(double delay, Event @event) {
+      Schedule(TimeSpan.FromSeconds(DefaultTimeStepSeconds * delay), @event);
+    }
+
+    /// <summary>
+    /// Schedules an event to occur at the same simulation time as the call was made.
+    /// </summary>
+    /// <param name="event">The event that should be scheduled.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public virtual void Schedule(Event @event, int priority = 0) {
+      DoSchedule(Now, @event, priority);
+    }
+
+    /// <summary>
+    /// Schedules an event to occur after a certain (positive) delay.
+    /// </summary>
+    /// <exception cref="ArgumentException">
+    /// Thrown when <paramref name="delay"/> is negative.
+    /// </exception>
+    /// <param name="delay">The (positive) delay after which the event should be fired.</param>
+    /// <param name="event">The event that should be scheduled.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public virtual void Schedule(TimeSpan delay, Event @event, int priority = 0) {
+      if (delay < TimeSpan.Zero)
+        throw new ArgumentException("Negative delays are not allowed in Schedule(TimeSpan, Event).");
+      var eventTime = Now + delay;
+      DoSchedule(eventTime, @event, priority);
+    }
+
+    protected virtual EventQueueNode DoSchedule(DateTime date, Event @event, int priority = 0) {
+      if (ScheduleQ.MaxSize == ScheduleQ.Count) {
+        // the capacity has to be adjusted, there are more events in the queue than anticipated
+        var oldSchedule = ScheduleQ;
+        ScheduleQ = new EventQueue(ScheduleQ.MaxSize * 2);
+        foreach (var e in oldSchedule) ScheduleQ.Enqueue(e.PrimaryPriority, e.Event, e.SecondaryPriority);
+      }
+      return ScheduleQ.Enqueue(date, @event, priority);
+    }
+
+    public virtual object RunD(double? until = null) {
+      if (!until.HasValue) return Run();
+      return Run(Now + TimeSpan.FromSeconds(DefaultTimeStepSeconds * until.Value));
+    }
+
+    public virtual object Run(TimeSpan span) {
+      return Run(Now + span);
+    }
+
+    public virtual object Run(DateTime until) {
+      if (until <= Now) throw new InvalidOperationException("Simulation end date must lie in the future.");
+      var stopEvent = new Event(this);
+      var node = DoSchedule(until, stopEvent);
+      // stop event is always the first to execute at the given time
+      node.InsertionIndex = -1;
+      ScheduleQ.OnNodeUpdated(node);
+      return Run(stopEvent);
+    }
+
+    protected bool _stopRequested = false;
+    /// <summary>
+    /// Run until a certain event is processed.
+    /// </summary>
+    /// <remarks>
+    /// This simulation environment is not thread-safe, thus triggering this event outside the environment
+    /// leads to potential race conditions. Please use the <see cref="ThreadSafeSimulation"/> environment in case you
+    /// require this functionality. Note that the performance of <see cref="ThreadSafeSimulation"/> is lower due to locking.
+    /// 
+    /// For real-time based termination, you can also call <see cref="StopAsync"/> which sets a flag indicating the simulation
+    /// to stop before processing the next event.
+    /// </remarks>
+    /// <param name="stopEvent">The event that stops the simulation.</param>
+    /// <returns></returns>
+    public virtual object Run(Event stopEvent = null) {
+      _stopRequested = false;
+      if (stopEvent != null) {
+        if (stopEvent.IsProcessed) return stopEvent.Value;
+        stopEvent.AddCallback(StopSimulation);
+      }
+
+      try {
+        var stop = ScheduleQ.Count == 0 || _stopRequested;
+        while (!stop) {
+          Step();
+          ProcessedEvents++;
+          stop = ScheduleQ.Count == 0 || _stopRequested;
+        }
+      } catch (StopSimulationException e) { return e.Value; }
+      if (stopEvent == null) return null;
+      if (!stopEvent.IsTriggered) throw new InvalidOperationException("No scheduled events left but \"until\" event was not triggered.");
+      return stopEvent.Value;
+    }
+
+    public virtual void StopAsync() {
+      _stopRequested = true;
+    }
+
+    /// <summary>
+    /// Performs a single step of the simulation, i.e. process a single event
+    /// </summary>
+    /// <remarks>
+    /// This method is not thread-safe
+    /// </remarks>
+    public virtual void Step() {
+      Event evt;
+      var next = ScheduleQ.Dequeue();
+      Now = next.PrimaryPriority;
+      evt = next.Event;
+      evt.Process();
+    }
+
+    /// <summary>
+    /// Peeks at the time of the next event in terms of the defined step
+    /// </summary>
+    /// <remarks>
+    /// This method is not thread-safe
+    /// </remarks>
+    public virtual double PeekD() {
+      if (ScheduleQ.Count == 0) return double.MaxValue;
+      return (Peek() - StartDate).TotalSeconds / DefaultTimeStepSeconds;
+    }
+
+    /// <summary>
+    /// Peeks at the time of the next event
+    /// </summary>
+    /// <remarks>
+    /// This method is not thread-safe
+    /// </remarks>
+    public virtual DateTime Peek() {
+      return ScheduleQ.Count > 0 ? ScheduleQ.First.PrimaryPriority : DateTime.MaxValue;
+    }
+
+    protected virtual void StopSimulation(Event @event) {
+      throw new StopSimulationException(@event.Value);
+    }
+
+    public virtual void Log(string message, params object[] args) {
+      if (Logger != null)
+        Logger.WriteLine(message, args);
+    }
+
+    #region Random number distributions
+    public double RandUniform(IRandom random, double a, double b) {
+      return a + (b - a) * random.NextDouble();
+    }
+    public double RandUniform(double a, double b) {
+      return RandUniform(Random, a, b);
+    }
+
+    public TimeSpan RandUniform(IRandom random, TimeSpan a, TimeSpan b) {
+      return TimeSpan.FromSeconds(RandUniform(random, a.TotalSeconds, b.TotalSeconds));
+    }
+    public TimeSpan RandUniform(TimeSpan a, TimeSpan b) {
+      return RandUniform(Random, a, b);
+    }
+    public double RandTriangular(IRandom random, double low, double high) {
+      var u = random.NextDouble();
+      if (u > 0.5)
+        return high + (low - high) * Math.Sqrt(((1.0 - u) / 2));
+      return low + (high - low) * Math.Sqrt(u / 2);
+    }
+    public double RandTriangular(double low, double high) {
+      return RandTriangular(Random, low, high);
+    }
+
+    public TimeSpan RandTriangular(IRandom random, TimeSpan low, TimeSpan high) {
+      return TimeSpan.FromSeconds(RandTriangular(random, low.TotalSeconds, high.TotalSeconds));
+    }
+    public TimeSpan RandTriangular(TimeSpan low, TimeSpan high) {
+      return RandTriangular(Random, low, high);
+    }
+
+    public double RandTriangular(IRandom random, double low, double high, double mode) {
+      var u = random.NextDouble();
+      var c = (mode - low) / (high - low);
+      if (u > c)
+        return high + (low - high) * Math.Sqrt(((1.0 - u) * (1.0 - c)));
+      return low + (high - low) * Math.Sqrt(u * c);
+    }
+    public double RandTriangular(double low, double high, double mode) {
+      return RandTriangular(Random, low, high, mode);
+    }
+
+    public TimeSpan RandTriangular(IRandom random, TimeSpan low, TimeSpan high, TimeSpan mode) {
+      return TimeSpan.FromSeconds(RandTriangular(random, low.TotalSeconds, high.TotalSeconds, mode.TotalSeconds));
+    }
+    public TimeSpan RandTriangular(TimeSpan low, TimeSpan high, TimeSpan mode) {
+      return RandTriangular(Random, low, high, mode);
+    }
+
+    /// <summary>
+    /// Returns a number that is exponentially distributed given a certain mean.
+    /// </summary>
+    /// <remarks>
+    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
+    /// </remarks>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
+    /// <returns>A number that is exponentially distributed</returns>
+    public double RandExponential(IRandom random, double mean) {
+      return -Math.Log(1 - random.NextDouble()) * mean;
+    }
+    /// <summary>
+    /// Returns a number that is exponentially distributed given a certain mean.
+    /// </summary>
+    /// <remarks>
+    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
+    /// </remarks>
+    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
+    /// <returns>A number that is exponentially distributed</returns>
+    public double RandExponential(double mean) {
+      return RandExponential(Random, mean);
+    }
+
+    /// <summary>
+    /// Returns a timespan that is exponentially distributed given a certain mean.
+    /// </summary>
+    /// <remarks>
+    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
+    /// </remarks>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
+    /// <returns>A number that is exponentially distributed</returns>
+    public TimeSpan RandExponential(IRandom random, TimeSpan mean) {
+      return TimeSpan.FromSeconds(RandExponential(random, mean.TotalSeconds));
+    }
+    /// <summary>
+    /// Returns a timespan that is exponentially distributed given a certain mean.
+    /// </summary>
+    /// <remarks>
+    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
+    /// </remarks>
+    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
+    /// <returns>A number that is exponentially distributed</returns>
+    public TimeSpan RandExponential(TimeSpan mean) {
+      return RandExponential(Random, mean);
+    }
+
+    private bool useSpareNormal = false;
+    private double spareNormal = double.NaN;
+    /// <summary>
+    /// Uses the Marsaglia polar method to generate a random variable
+    /// from two uniform random distributed values.
+    /// </summary>
+    /// <remarks>
+    /// A spare random variable is generated from the second uniformly
+    /// distributed value. Thus, the two calls to the uniform random number
+    /// generator will be made only every second call.
+    /// </remarks>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mu">The mean of the normal distribution.</param>
+    /// <param name="sigma">The standard deviation of the normal distribution.</param>
+    /// <returns>A number that is normal distributed.</returns>
+    public virtual double RandNormal(IRandom random, double mu, double sigma) {
+      if (useSpareNormal) {
+        useSpareNormal = false;
+        return spareNormal * sigma + mu;
+      } else {
+        double u, v, s;
+        do {
+          u = random.NextDouble() * 2 - 1;
+          v = random.NextDouble() * 2 - 1;
+          s = u * u + v * v;
+        } while (s >= 1 || s == 0);
+        var mul = Math.Sqrt(-2.0 * Math.Log(s) / s);
+        spareNormal = v * mul;
+        useSpareNormal = true;
+        return mu + sigma * u * mul;
+      }
+    }
+    /// <summary>
+    /// Uses the Marsaglia polar method to generate a random variable
+    /// from two uniform random distributed values.
+    /// </summary>
+    /// <remarks>
+    /// A spare random variable is generated from the second uniformly
+    /// distributed value. Thus, the two calls to the uniform random number
+    /// generator will be made only every second call.
+    /// </remarks>
+    /// <param name="mu">The mean of the normal distribution.</param>
+    /// <param name="sigma">The standard deviation of the normal distribution.</param>
+    /// <returns>A number that is normal distributed.</returns>
+    public double RandNormal(double mu, double sigma) {
+      return RandNormal(Random, mu, sigma);
+    }
+
+    /// <summary>
+    /// Uses the Marsaglia polar method to generate a random variable
+    /// from two uniform random distributed values.
+    /// </summary>
+    /// <remarks>
+    /// A spare random variable is generated from the second uniformly
+    /// distributed value. Thus, the two calls to the uniform random number
+    /// generator will be made only every second call.
+    /// </remarks>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mu">The mean of the normal distribution.</param>
+    /// <param name="sigma">The standard deviation of the normal distribution.</param>
+    /// <returns>A number that is normal distributed.</returns>
+    public TimeSpan RandNormal(IRandom random, TimeSpan mu, TimeSpan sigma) {
+      return TimeSpan.FromSeconds(RandNormal(random, mu.TotalSeconds, sigma.TotalSeconds));
+    }
+    /// <summary>
+    /// Uses the Marsaglia polar method to generate a random variable
+    /// from two uniform random distributed values.
+    /// </summary>
+    /// <remarks>
+    /// A spare random variable is generated from the second uniformly
+    /// distributed value. Thus, the two calls to the uniform random number
+    /// generator will be made only every second call.
+    /// </remarks>
+    /// <param name="mu">The mean of the normal distribution.</param>
+    /// <param name="sigma">The standard deviation of the normal distribution.</param>
+    /// <returns>A number that is normal distributed.</returns>
+    public TimeSpan RandNormal(TimeSpan mu, TimeSpan sigma) {
+      return RandNormal(Random, mu, sigma);
+    }
+
+    public double RandNormalPositive(IRandom random, double mu, double sigma) {
+      double val;
+      do {
+        val = RandNormal(random, mu, sigma);
+      } while (val <= 0);
+      return val;
+    }
+    public double RandNormalPositive(double mu, double sigma) {
+      return RandNormalPositive(Random, mu, sigma);
+    }
+
+    public TimeSpan RandNormalPositive(IRandom random, TimeSpan mu, TimeSpan sigma) {
+      return TimeSpan.FromSeconds(RandNormalPositive(random, mu.TotalSeconds, sigma.TotalSeconds));
+    }
+    public TimeSpan RandNormalPositive(TimeSpan mu, TimeSpan sigma) {
+      return RandNormalPositive(Random, mu, sigma);
+    }
+
+    public double RandNormalNegative(IRandom random, double mu, double sigma) {
+      double val;
+      do {
+        val = RandNormal(random, mu, sigma);
+      } while (val >= 0);
+      return val;
+    }
+    public double RandNormalNegative(double mu, double sigma) {
+      return RandNormalNegative(Random, mu, sigma);
+    }
+
+    public TimeSpan RandNormalNegative(IRandom random, TimeSpan mu, TimeSpan sigma) {
+      return TimeSpan.FromSeconds(RandNormalNegative(random, mu.TotalSeconds, sigma.TotalSeconds));
+    }
+    public TimeSpan RandNormalNegative(TimeSpan mu, TimeSpan sigma) {
+      return RandNormalNegative(Random, mu, sigma);
+    }
+
+    /// <summary>
+    /// Returns values from a log-normal distribution with the mean
+    /// exp(mu + sigma^2 / 2)
+    /// and the standard deviation
+    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
+    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
+    /// <returns>A log-normal distributed random value.</returns>
+    public double RandLogNormal(IRandom random, double mu, double sigma) {
+      return Math.Exp(RandNormal(random, mu, sigma));
+    }
+    /// <summary>
+    /// Returns values from a log-normal distribution with the mean
+    /// exp(mu + sigma^2 / 2)
+    /// and the standard deviation
+    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
+    /// </summary>
+    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
+    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
+    /// <returns>A log-normal distributed random value.</returns>
+    public double RandLogNormal(double mu, double sigma) {
+      return RandLogNormal(Random, mu, sigma);
+    }
+
+    /// <summary>
+    /// Returns values from a log-normal distribution with
+    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mean">The distribution mean.</param>
+    /// <param name="stdev">The distribution standard deviation.</param>
+    /// <returns>A log-normal distributed random value.</returns>
+    public double RandLogNormal2(IRandom random, double mean, double stdev) {
+      if (stdev == 0) return mean;
+      var alpha = Math.Sqrt(mean * stdev) / mean;
+      var sigma = Math.Sqrt(Math.Log(1 + (alpha * alpha)));
+      var mu = Math.Log(mean) - 0.5 * sigma * sigma;
+      return Math.Exp(RandNormal(random, mu, sigma));
+    }
+    /// <summary>
+    /// Returns values from a log-normal distribution with
+    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
+    /// </summary>
+    /// <param name="mean">The distribution mean.</param>
+    /// <param name="stdev">The distribution standard deviation.</param>
+    /// <returns>A log-normal distributed random value.</returns>
+    public double RandLogNormal2(double mean, double stdev) {
+      return RandLogNormal2(Random, mean, stdev);
+    }
+
+    /// <summary>
+    /// Returns a timespan value from a log-normal distribution with the mean
+    /// exp(mu + sigma^2 / 2)
+    /// and the standard deviation
+    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
+    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
+    /// <returns>A log-normal distributed random timespan.</returns>
+    public TimeSpan RandLogNormal(IRandom random, TimeSpan mu, TimeSpan sigma) {
+      return TimeSpan.FromSeconds(RandLogNormal(random, mu.TotalSeconds, sigma.TotalSeconds));
+    }
+    /// <summary>
+    /// Returns a timespan value from a log-normal distribution with the mean
+    /// exp(mu + sigma^2 / 2)
+    /// and the standard deviation
+    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
+    /// </summary>
+    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
+    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
+    /// <returns>A log-normal distributed random timespan.</returns>
+    public TimeSpan RandLogNormal(TimeSpan mu, TimeSpan sigma) {
+      return RandLogNormal(Random, mu, sigma);
+    }
+
+    /// <summary>
+    /// Returns a timespan value from a log-normal distribution with
+    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
+    /// </summary>
+    /// <param name="random">The random number generator to use.</param>
+    /// <param name="mean">The distribution mean.</param>
+    /// <param name="stdev">The distribution standard deviation.</param>
+    /// <returns>A log-normal distributed random timespan.</returns>
+    public TimeSpan RandLogNormal2(IRandom random, TimeSpan mean, TimeSpan stdev) {
+      return TimeSpan.FromSeconds(RandLogNormal2(random, mean.TotalSeconds, stdev.TotalSeconds));
+    }
+    /// <summary>
+    /// Returns a timespan value from a log-normal distribution with
+    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
+    /// </summary>
+    /// <param name="mean">The distribution mean.</param>
+    /// <param name="stdev">The distribution standard deviation.</param>
+    /// <returns>A log-normal distributed random timespan.</returns>
+    public TimeSpan RandLogNormal2(TimeSpan mean, TimeSpan stdev) {
+      return RandLogNormal2(Random, mean, stdev);
+    }
+
+    public double RandCauchy(IRandom random, double x0, double gamma) {
+      return x0 + gamma * Math.Tan(Math.PI * (random.NextDouble() - 0.5));
+    }
+    public double RandCauchy(double x0, double gamma) {
+      return RandCauchy(Random, x0, gamma);
+    }
+
+    public TimeSpan RandCauchy(IRandom random, TimeSpan x0, TimeSpan gamma) {
+      return TimeSpan.FromSeconds(RandCauchy(random, x0.TotalSeconds, gamma.TotalSeconds));
+    }
+    public TimeSpan RandCauchy(TimeSpan x0, TimeSpan gamma) {
+      return RandCauchy(Random, x0, gamma);
+    }
+
+    public double RandWeibull(IRandom random, double alpha, double beta) {
+      return alpha * Math.Pow(-Math.Log(1 - random.NextDouble()), 1 / beta);
+    }
+    public double RandWeibull(double alpha, double beta) {
+      return RandWeibull(Random, alpha, beta);
+    }
+
+    public TimeSpan RandWeibull(IRandom random, TimeSpan alpha, TimeSpan beta) {
+      return TimeSpan.FromSeconds(RandWeibull(random, alpha.TotalSeconds, beta.TotalSeconds));
+    }
+    public TimeSpan RandWeibull(TimeSpan alpha, TimeSpan beta) {
+      return RandWeibull(Random, alpha, beta);
+    }
+    #endregion
+
+    #region Random timeouts
+    public Timeout TimeoutUniformD(IRandom random, double a, double b) {
+      return new Timeout(this, ToTimeSpan(RandUniform(random, a, b)));
+    }
+    public Timeout TimeoutUniformD(double a, double b) {
+      return TimeoutUniformD(Random, a, b);
+    }
+
+    public Timeout TimeoutUniform(IRandom random, TimeSpan a, TimeSpan b) {
+      return new Timeout(this, RandUniform(random, a, b));
+    }
+    public Timeout TimeoutUniform(TimeSpan a, TimeSpan b) {
+      return TimeoutUniform(Random, a, b);
+    }
+
+    public Timeout TimeoutTriangularD(IRandom random, double low, double high) {
+      return new Timeout(this, ToTimeSpan(RandTriangular(random, low, high)));
+    }
+    public Timeout TimeoutTriangularD(double low, double high) {
+      return TimeoutTriangularD(Random, low, high);
+    }
+
+    public Timeout TimeoutTriangular(IRandom random, TimeSpan low, TimeSpan high) {
+      return new Timeout(this, RandTriangular(random, low, high));
+    }
+    public Timeout TimeoutTriangular(TimeSpan low, TimeSpan high) {
+      return TimeoutTriangular(Random, low, high);
+    }
+
+    public Timeout TimeoutTriangularD(IRandom random, double low, double high, double mode) {
+      return new Timeout(this, ToTimeSpan(RandTriangular(random, low, high, mode)));
+    }
+    public Timeout TimeoutTriangularD(double low, double high, double mode) {
+      return TimeoutTriangularD(Random, low, high, mode);
+    }
+
+    public Timeout TimeoutTriangular(IRandom random, TimeSpan low, TimeSpan high, TimeSpan mode) {
+      return new Timeout(this, RandTriangular(random, low, high, mode));
+    }
+    public Timeout TimeoutTriangular(TimeSpan low, TimeSpan high, TimeSpan mode) {
+      return TimeoutTriangular(Random, low, high, mode);
+    }
+
+    public Timeout TimeoutExponentialD(IRandom random, double mean) {
+      return new Timeout(this, ToTimeSpan(RandExponential(random, mean)));
+    }
+    public Timeout TimeoutExponentialD(double mean) {
+      return TimeoutExponentialD(Random, mean);
+    }
+
+    public Timeout TimeoutExponential(IRandom random, TimeSpan mean) {
+      return new Timeout(this, RandExponential(random, mean));
+    }
+    public Timeout TimeoutExponential(TimeSpan mean) {
+      return TimeoutExponential(Random, mean);
+    }
+
+    public Timeout TimeoutNormalPositiveD(IRandom random, double mu, double sigma) {
+      return new Timeout(this, ToTimeSpan(RandNormalPositive(random, mu, sigma)));
+    }
+    public Timeout TimeoutNormalPositiveD(double mu, double sigma) {
+      return TimeoutNormalPositiveD(Random, mu, sigma);
+    }
+
+    public Timeout TimeoutNormalPositive(IRandom random, TimeSpan mu, TimeSpan sigma) {
+      return new Timeout(this, RandNormalPositive(random, mu, sigma));
+    }
+    public Timeout TimeoutNormalPositive(TimeSpan mu, TimeSpan sigma) {
+      return TimeoutNormalPositive(Random, mu, sigma);
+    }
+
+    public Timeout TimeoutLogNormalD(IRandom random, double mu, double sigma) {
+      return new Timeout(this, ToTimeSpan(RandLogNormal(random, mu, sigma)));
+    }
+    public Timeout TimeoutLogNormalD(double mu, double sigma) {
+      return TimeoutLogNormalD(Random, mu, sigma);
+    }
+
+    public Timeout TimeoutLogNormal2D(IRandom random, double mean, double stdev) {
+      return new Timeout(this, ToTimeSpan(RandLogNormal2(random, mean, stdev)));
+    }
+    public Timeout TimeoutLogNormal2D(double mean, double stdev) {
+      return TimeoutLogNormal2D(Random, mean, stdev);
+    }
+
+    public Timeout TimeoutLogNormal(IRandom random, TimeSpan mu, TimeSpan sigma) {
+      return new Timeout(this, RandLogNormal(random, mu, sigma));
+    }
+    public Timeout TimeoutLogNormal(TimeSpan mu, TimeSpan sigma) {
+      return TimeoutLogNormal(Random, mu, sigma);
+    }
+
+    public Timeout TimeoutLogNormal2(IRandom random, TimeSpan mean, TimeSpan stdev) {
+      return new Timeout(this, RandLogNormal2(random, mean, stdev));
+    }
+    public Timeout TimeoutLogNormal2(TimeSpan mean, TimeSpan stdev) {
+      return TimeoutLogNormal2(Random, mean, stdev);
+    }
+    #endregion
+  }
+
+  /// <summary>
+  /// Provides a simulation environment that is thread-safe against manipulations of the event queue.
+  /// Its performance is somewhat lower than the non-thread-safe environment (cf. <see cref="Simulation"/>)
+  /// due to the locking involved.
+  /// </summary>
+  /// <remarks>
+  /// Please carefully consider if you must really schedule the stop event in a separate thread. You can also
+  /// call <see cref="Simulation.StopAsync"/> to request termination after the current event has been processed.
+  /// 
+  /// The simulation will still run in only one thread and execute all events sequentially.
+  /// </remarks>
+  public class ThreadSafeSimulation : Simulation {
+    protected object _locker;
+
+    public ThreadSafeSimulation() : this(new DateTime(1970, 1, 1)) { }
+    public ThreadSafeSimulation(TimeSpan? defaultStep) : this(new DateTime(1970, 1, 1), defaultStep) { }
+    public ThreadSafeSimulation(DateTime initialDateTime, TimeSpan? defaultStep = null) : this(new PcgRandom(), initialDateTime, defaultStep) { }
+    public ThreadSafeSimulation(int randomSeed, TimeSpan? defaultStep = null) : this(new DateTime(1970, 1, 1), randomSeed, defaultStep) { }
+    public ThreadSafeSimulation(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null) : this(new PcgRandom(randomSeed), initialDateTime, defaultStep) { }
+    public ThreadSafeSimulation(IRandom random, DateTime initialDateTime, TimeSpan? defaultStep = null) : base(random, initialDateTime, defaultStep) {
+      _locker = new object();
+    }
+
+
+    /// <summary>
+    /// Schedules an event to occur at the same simulation time as the call was made.
+    /// </summary>
+    /// <remarks>
+    /// This method is thread-safe against manipulations of the event queue
+    /// </remarks>
+    /// <param name="event">The event that should be scheduled.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public override void Schedule(Event @event, int priority = 0) {
+      lock (_locker) {
+        DoSchedule(Now, @event, priority);
+      }
+    }
+
+    /// <summary>
+    /// Schedules an event to occur after a certain (positive) delay.
+    /// </summary>
+    /// <remarks>
+    /// This method is thread-safe against manipulations of the event queue
+    /// </remarks>
+    /// <exception cref="ArgumentException">
+    /// Thrown when <paramref name="delay"/> is negative.
+    /// </exception>
+    /// <param name="delay">The (positive) delay after which the event should be fired.</param>
+    /// <param name="event">The event that should be scheduled.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public override void Schedule(TimeSpan delay, Event @event, int priority = 0) {
+      if (delay < TimeSpan.Zero)
+        throw new ArgumentException("Negative delays are not allowed in Schedule(TimeSpan, Event).");
+      lock (_locker) {
+        var eventTime = Now + delay;
+        DoSchedule(eventTime, @event, priority);
+      }
+    }
+
+    /// <summary>
+    /// Run until a certain event is processed.
+    /// </summary>
+    /// <remarks>
+    /// This method is thread-safe against manipulations of the event queue
+    /// </remarks>
+    /// <param name="stopEvent">The event that stops the simulation.</param>
+    /// <returns></returns>
+    public override object Run(Event stopEvent = null) {
+      _stopRequested = false;
+      if (stopEvent != null) {
+        if (stopEvent.IsProcessed) return stopEvent.Value;
+        stopEvent.AddCallback(StopSimulation);
+      }
+
+      try {
+        var stop = false;
+        lock (_locker) {
+          stop = ScheduleQ.Count == 0 || _stopRequested;
+        }
+        while (!stop) {
+          Step();
+          ProcessedEvents++;
+          lock (_locker) {
+            stop = ScheduleQ.Count == 0 || _stopRequested;
+          }
+        }
+      } catch (StopSimulationException e) { return e.Value; }
+      if (stopEvent == null) return null;
+      if (!stopEvent.IsTriggered) throw new InvalidOperationException("No scheduled events left but \"until\" event was not triggered.");
+      return stopEvent.Value;
+    }
+
+    /// <summary>
+    /// Performs a single step of the simulation, i.e. process a single event
+    /// </summary>
+    /// <remarks>
+    /// This method is thread-safe against manipulations of the event queue
+    /// </remarks>
+    public override void Step() {
+      Event evt;
+      lock (_locker) {
+        var next = ScheduleQ.Dequeue();
+        Now = next.PrimaryPriority;
+        evt = next.Event;
+      }
+      evt.Process();
+    }
+
+    /// <summary>
+    /// Peeks at the time of the next event in terms of the defined step
+    /// </summary>
+    /// <remarks>
+    /// This method is thread-safe against manipulations of the event queue
+    /// </remarks>
+    public override double PeekD() {
+      lock (_locker) {
+        if (ScheduleQ.Count == 0) return double.MaxValue;
+        return (Peek() - StartDate).TotalSeconds / DefaultTimeStepSeconds;
+      }
+    }
+
+    /// <summary>
+    /// Peeks at the time of the next event
+    /// </summary>
+    /// <remarks>
+    /// This method is thread-safe against manipulations of the event queue
+    /// </remarks>
+    public override DateTime Peek() {
+      lock (_locker) {
+        return ScheduleQ.Count > 0 ? ScheduleQ.First.PrimaryPriority : DateTime.MaxValue;
+      }
+    }
+  }
+
+  /// <summary>
+  /// Environments hold the event queues, schedule and process events.
+  /// </summary>
+  [Obsolete("Use class Simulation or ThreadSafeSimulation instead. Due to name clashes with System.Environment the class SimSharp.Environment is being outphased.")]
+  public class Environment : ThreadSafeSimulation {
+    public Environment()
+      : base() {
+      Random = new SystemRandom();
+    }
+    public Environment(TimeSpan? defaultStep)
+      : base(defaultStep) {
+      Random = new SystemRandom();
+    }
+    public Environment(int randomSeed, TimeSpan? defaultStep = null)
+      : base(randomSeed, defaultStep) {
+      Random = new SystemRandom(randomSeed);
+    }
+    public Environment(DateTime initialDateTime, TimeSpan? defaultStep = null)
+      : base(initialDateTime, defaultStep) {
+      Random = new SystemRandom();
+    }
+    public Environment(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null)
+      : base(initialDateTime, randomSeed, defaultStep) {
+      Random = new SystemRandom(randomSeed);
+    }
+
+    protected static readonly double NormalMagicConst = 4 * Math.Exp(-0.5) / Math.Sqrt(2.0);
+    public override double RandNormal(IRandom random, double mu, double sigma) {
+      double z, zz, u1, u2;
+      do {
+        u1 = random.NextDouble();
+        u2 = 1 - random.NextDouble();
+        z = NormalMagicConst * (u1 - 0.5) / u2;
+        zz = z * z / 4.0;
+      } while (zz > -Math.Log(u2));
+      return mu + z * sigma;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AllOf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AllOf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AllOf.cs	(revision 16892)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System.Collections.Generic;
+
+namespace SimSharp {
+  public class AllOf : Condition {
+    public AllOf(Simulation environment, params Event[] events) : base(environment, events) { }
+    public AllOf(Simulation environment, IEnumerable<Event> events) : base(environment, events) { }
+
+    protected override bool Evaluate() {
+      return FiredEvents.Count == Events.Count;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AnyOf.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AnyOf.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AnyOf.cs	(revision 16892)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System.Collections.Generic;
+
+namespace SimSharp {
+  public class AnyOf : Condition {
+    public AnyOf(Simulation environment, params Event[] events) : base(environment, events) { }
+    public AnyOf(Simulation environment, IEnumerable<Event> events) : base(environment, events) { }
+
+    protected override bool Evaluate() {
+      return FiredEvents.Count > 0 || Events.Count == 0;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Condition.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Condition.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Condition.cs	(revision 16892)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+
+namespace SimSharp {
+  /// <summary>
+  /// Conditions are events that execute when any or all of its sub-events are executed.
+  /// </summary>
+  public abstract class Condition : Event {
+
+    public new OrderedDictionary Value {
+      get { return (OrderedDictionary)base.Value; }
+      set { base.Value = value; }
+    }
+
+    protected List<Event> Events { get; private set; }
+
+    protected List<Event> FiredEvents { get; private set; }
+
+    protected Condition(Simulation environment, params Event[] events)
+      : this(environment, (IEnumerable<Event>)events) { }
+    protected Condition(Simulation environment, IEnumerable<Event> events)
+      : base(environment) {
+      CallbackList.Add(CollectValues);
+      Events = new List<Event>(events);
+      FiredEvents = new List<Event>();
+
+      foreach (var @event in Events) {
+        if (Environment != @event.Environment)
+          throw new ArgumentException("It is not allowed to mix events from different environments");
+        if (@event.IsProcessed) Check(@event);
+        else @event.AddCallback(Check);
+      }
+
+      if (IsAlive && Evaluate())
+        Succeed();
+    }
+
+    protected void Check(Event @event) {
+      if (IsTriggered || IsProcessed) {
+        if (!@event.IsOk) throw new InvalidOperationException(
+@"Errors that happen after the condition has been triggered will not be
+handled by the condition and cause the simulation to crash.");
+        return;
+      }
+      FiredEvents.Add(@event);
+
+      if (!@event.IsOk)
+        Fail(@event.Value);
+      else if (Evaluate()) {
+        Succeed();
+      }
+    }
+
+    protected virtual IEnumerable<KeyValuePair<object, object>> GetValues() {
+      var values = new List<KeyValuePair<object, object>>();
+      foreach (var e in Events) {
+        var condition = e as Condition;
+        if (condition != null) {
+          values.AddRange(condition.GetValues());
+        } else if (e.IsProcessed) {
+          values.Add(new KeyValuePair<object, object>(e, e.Value));
+        }
+      }
+      return values;
+    }
+
+    protected virtual void CollectValues(Event @event) {
+      if (@event.IsOk) {
+        var value = new OrderedDictionary();
+        foreach (var v in GetValues())
+          value.Add(v.Key, v.Value);
+        Value = value;
+      }
+    }
+
+    protected abstract bool Evaluate();
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Event.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Event.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Event.cs	(revision 16892)
@@ -0,0 +1,200 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// The base class for all events in SimSharp.
+  /// An event can be in one of three states at any time:
+  ///  - Alive: The event object exists, but is neither scheduled to
+  ///           be executed, nor is it already executed.
+  ///  - Triggered: The event has been put in the event queue and is
+  ///               going to be executed.
+  ///  - Processed: The event has been executed.
+  /// 
+  /// Usually, the event is alive until its Trigger, Succeed, or Fail
+  /// method have been called. Then it becomes triggered. When the
+  /// Environment progresses to the event and executes its callbacks
+  /// the event becomes processed.
+  /// </summary>
+  public class Event {
+    protected internal Simulation Environment { get; private set; }
+    protected List<Action<Event>> CallbackList { get; set; }
+
+    /// <summary>
+    /// The value property can be used to return arbitrary data from a
+    /// process or an event. It also represents the interrupt cause to
+    /// a process.
+    /// </summary>
+    public object Value { get; protected set; }
+
+    /// <summary>
+    /// The IsOk flag indicates if the event succeeded or failed. An event
+    /// that failed indicates to a waiting process that the action could
+    /// not be performed and that the faulting situation must be handled.
+    /// Typically, interrupting a process sets the IsOk flag to false.
+    /// </summary>
+    public bool IsOk { get; protected set; }
+    /// <summary>
+    /// An event is alive when it is not triggered and not processed. That
+    /// is, when it exists in memory without being scheduled. Typically,
+    /// a Process is alive until its last event has been processed and the
+    /// process event itself is to be processed.
+    /// </summary>
+    public bool IsAlive { get { return !IsTriggered && !IsProcessed; } }
+    /// <summary>
+    /// An event becomes processed when its callbacks have been executed.
+    /// Events may only be processed once and an exception will be thrown
+    /// if they are to be processed multiple times.
+    /// </summary>
+    public bool IsProcessed { get; protected set; }
+    /// <summary>
+    /// An event becomes triggered when it is placed into the event queue.
+    /// That is, when its callbacks are going to be executed.
+    /// An even that is triggered may later not be failed or retriggered.
+    /// </summary>
+    public bool IsTriggered { get; protected set; }
+
+    public Event(Simulation environment) {
+      Environment = environment;
+      CallbackList = new List<Action<Event>>();
+    }
+
+    /// <summary>
+    /// This method schedules the event right now. It takes the IsOk state
+    /// and uses the <see cref="Value"/> of the given <paramref name="@event"/>.
+    /// Thus if the given event fails, this event will also be triggered as
+    /// failing.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">
+    /// Thrown when the event has already been triggered.
+    /// </exception>
+    /// <remarks>
+    /// The signature of this method allows it to be used as a callback.
+    /// </remarks>
+    /// <param name="event">The event that triggers this event.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public virtual void Trigger(Event @event, int priority = 0) {
+      if (IsTriggered)
+        throw new InvalidOperationException("Event has already been triggered.");
+      IsOk = @event.IsOk;
+      Value = @event.Value;
+      IsTriggered = true;
+      Environment.Schedule(this, priority);
+    }
+
+    /// <summary>
+    /// This method schedules the event right now. It sets IsOk state to true
+    /// and optionally uses also the value. If urgent is given, the event may
+    /// be scheduled as urgent. Urgent events are placed in a separate event
+    /// queue. The callbacks of urgent events are executed before normal events.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">
+    /// Thrown when the event has already been triggered.
+    /// </exception>
+    /// <param name="value">The value that the event should use.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public virtual void Succeed(object value = null, int priority = 0) {
+      if (IsTriggered)
+        throw new InvalidOperationException("Event has already been triggered.");
+      IsOk = true;
+      Value = value;
+      IsTriggered = true;
+      Environment.Schedule(this, priority);
+    }
+
+    /// <summary>
+    /// This method schedules the event right now. It sets IsOk state to false
+    /// and optionally uses also the value. If urgent is given, the event may
+    /// be scheduled as urgent. Urgent events are placed in a separate event
+    /// queue. The callbacks of urgent events are executed before normal events.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">
+    /// Thrown when the event has already been triggered.
+    /// </exception>
+    /// <param name="value">The value that the event should use.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public virtual void Fail(object value = null, int priority = 0) {
+      if (IsTriggered)
+        throw new InvalidOperationException("Event has already been triggered.");
+      IsOk = false;
+      Value = value;
+      IsTriggered = true;
+      Environment.Schedule(this, priority);
+    }
+
+    /// <summary>
+    /// This method adds a callback to the list of callbacks. Callbacks will be
+    /// executed in the order they have been added.
+    /// </summary>
+    /// <param name="callback">The callback to execute when the event is being
+    /// processed.</param>
+    public virtual void AddCallback(Action<Event> callback) {
+      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
+      CallbackList.Add(callback);
+    }
+
+    /// <summary>
+    /// This method adds a range of callbacks to the list of callbacks. Callbacks
+    /// will be executed in the order they have been added.
+    /// </summary>
+    /// <param name="callbacks">The callbacks to execute when the event is being
+    /// processed.</param>
+    public virtual void AddCallbacks(IEnumerable<Action<Event>> callbacks) {
+      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
+      CallbackList.AddRange(callbacks);
+    }
+
+    /// <summary>
+    /// This method removes a callback to the list of callbacks.
+    /// </summary>
+    /// <remarks>
+    /// It is not checked if the callback has actually been added before and
+    /// no exception will be thrown if it had not been present.
+    /// </remarks>
+    /// <param name="callback">The callback to remove.</param>
+    public virtual void RemoveCallback(Action<Event> callback) {
+      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
+      CallbackList.Remove(callback);
+    }
+
+    /// <summary>
+    /// This method processes the event, that is, it calls all the callbacks.
+    /// When it finishes it will be marked IsProcessed and cannot be processed
+    /// again.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">When the event has already
+    /// been processed.</exception>
+    public virtual void Process() {
+      if (IsProcessed) throw new InvalidOperationException("Event has already been processed.");
+      IsProcessed = true;
+      for (var i = 0; i < CallbackList.Count; i++)
+        CallbackList[i](this);
+      CallbackList = null;
+    }
+
+    public static Condition operator &(Event event1, Event event2) {
+      return new AllOf(event1.Environment, event1, event2);
+    }
+    public static Condition operator |(Event event1, Event event2) {
+      return new AnyOf(event1.Environment, event1, event2);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Process.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Process.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Process.cs	(revision 16892)
@@ -0,0 +1,167 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// A Process handles the iteration of events. Processes may define steps that
+  /// a certain entity in the simulation has to perform. Each time the process
+  /// should wait it yields an event and will be resumed when that event is processed.
+  /// </summary>
+  /// <remarks>
+  /// Since an iterator method does not have access to its process, the method can
+  /// retrieve the associated Process through the ActiveProcess property of the
+  /// environment. Each Process sets and resets that property during Resume.
+  /// </remarks>
+  public class Process : Event {
+    private readonly IEnumerator<Event> generator;
+    private Event target;
+    /// <summary>
+    /// Target is the event that is expected to be executed next in the process.
+    /// </summary>
+    public Event Target {
+      get { return target; }
+      protected set { target = value; }
+    }
+
+    /// <summary>
+    /// Sets up a new process.
+    /// The process places an initialize event into the event queue which starts
+    /// the process by retrieving events from the generator.
+    /// </summary>
+    /// <param name="environment">The environment in which the process lives.</param>
+    /// <param name="generator">The generator function of the process.</param>
+    /// <param name="priority">The priority if multiple processes are started at the same time.</param>
+    public Process(Simulation environment, IEnumerable<Event> generator, int priority = 0)
+      : base(environment) {
+      this.generator = generator.GetEnumerator();
+      IsOk = true;
+      target = new Initialize(environment, this, priority);
+    }
+
+    /// <summary>
+    /// This interrupts a process and causes the IsOk flag to be set to false.
+    /// If a process is interrupted the iterator method needs to call HandleFault()
+    /// before continuing to yield further events.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">This is thrown in three conditions:
+    ///  - If the process has already been triggered.
+    ///  - If the process attempts to interrupt itself.
+    ///  - If the process continues to yield events despite being faulted.</exception>
+    /// <param name="cause">The cause of the interrupt.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public virtual void Interrupt(object cause = null, int priority = 0) {
+      if (IsTriggered) throw new InvalidOperationException("The process has terminated and cannot be interrupted.");
+      if (Environment.ActiveProcess == this) throw new InvalidOperationException("A process is not allowed to interrupt itself.");
+
+      var interruptEvent = new Event(Environment);
+      interruptEvent.AddCallback(Resume);
+      interruptEvent.Fail(cause, priority);
+
+      if (Target != null)
+        Target.RemoveCallback(Resume);
+    }
+
+    protected virtual void Resume(Event @event) {
+      Environment.ActiveProcess = this;
+      while (true) {
+        if (@event.IsOk) {
+          if (generator.MoveNext()) {
+            if (IsTriggered) {
+              // the generator called e.g. Environment.ActiveProcess.Fail
+              Environment.ActiveProcess = null;
+              return;
+            }
+            if (!ProceedToEvent()) {
+              @event = target;
+              continue;
+            } else break;
+          } else if (!IsTriggered) {
+            Succeed(@event.Value);
+            break;
+          } else break;
+        } else {
+          /* Fault handling differs from SimPy as in .NET it is not possible to inject an
+         * exception into an enumerator and it is impossible to put a yield return inside
+         * a try-catch block. In SimSharp the Process will set IsOk and will then move to
+         * the next yield in the generator. However, if after this move IsOk is still false
+         * we know that the error was not handled. It is assumed the error is handled if
+         * HandleFault() is called on the environment's ActiveProcess which will reset the
+         * flag. */
+          IsOk = false;
+          Value = @event.Value;
+
+          if (generator.MoveNext()) {
+            if (IsTriggered) {
+              // the generator called e.g. Environment.ActiveProcess.Fail
+              Environment.ActiveProcess = null;
+              return;
+            }
+            // if we move next, but IsOk is still false
+            if (!IsOk) throw new InvalidOperationException("The process did not react to being faulted.");
+            // otherwise HandleFault was called and the fault was handled
+            if (ProceedToEvent()) break;
+          } else if (!IsTriggered) {
+            if (!IsOk) Fail(@event.Value);
+            else Succeed(@event.Value);
+            break;
+          } else break;
+        }
+      }
+      Environment.ActiveProcess = null;
+    }
+    
+    protected virtual bool ProceedToEvent() {
+      target = generator.Current;
+      Value = target.Value;
+      if (target.IsProcessed) return false;
+      target.AddCallback(Resume);
+      return true;
+    }
+
+    /// <summary>
+    /// This method must be called to reset the IsOk flag of the process back to true.
+    /// The IsOk flag may be set to false if the process waited on an event that failed.
+    /// </summary>
+    /// <remarks>
+    /// In SimPy a faulting process would throw an exception which is then catched and
+    /// chained. In SimSharp catching exceptions from a yield is not possible as a yield
+    /// return statement may not throw an exception.
+    /// If a processes faulted the Value property may indicate a cause for the fault.
+    /// </remarks>
+    /// <returns>True if a faulting situation needs to be handled, false if the process
+    /// is okay and the last yielded event succeeded.</returns>
+    public virtual bool HandleFault() {
+      if (IsOk) return false;
+      IsOk = true;
+      return true;
+    }
+
+    private class Initialize : Event {
+      public Initialize(Simulation environment, Process process, int priority)
+        : base(environment) {
+        CallbackList.Add(process.Resume);
+        IsOk = true;
+        IsTriggered = true;
+        environment.Schedule(this, priority);
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Timeout.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Timeout.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Timeout.cs	(revision 16892)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  /// <summary>
+  /// Timeouts are simple events that are executed after a certain timespan has passed.
+  /// </summary>
+  public sealed class Timeout : Event {
+    /// <summary>
+    /// A timeout is an event that is executed after a certain timespan has passed.
+    /// </summary>
+    /// <remarks>
+    /// Timeout events are scheduled when they are created. They are always triggered
+    /// when they are created.
+    /// </remarks>
+    /// <param name="environment">The environment in which it is scheduled.</param>
+    /// <param name="delay">The timespan for the timeout.</param>
+    /// <param name="value">The value of the timeout.</param>
+    /// <param name="isOk">Whether the timeout should succeed or fail.</param>
+    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
+    public Timeout(Simulation environment, TimeSpan delay, object value = null, bool isOk = true, int priority = 0)
+      : base(environment) {
+      IsOk = isOk;
+      Value = value;
+      IsTriggered = true;
+      environment.Schedule(delay, this, priority);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Exceptions/EmptyScheduleException.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Exceptions/EmptyScheduleException.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Exceptions/EmptyScheduleException.cs	(revision 16892)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  /// <summary>
+  /// An exception that is thrown to stop the simulation.
+  /// </summary>
+  public class StopSimulationException : Exception {
+    public object Value { get; private set; }
+    
+    public StopSimulationException(object value) {
+      Value = value;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Preempted.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Preempted.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Preempted.cs	(revision 16892)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public sealed class Preempted {
+    public Process By { get; private set; }
+    public DateTime UsageSince { get; private set; }
+
+    public Preempted(Process by, DateTime usageSince) {
+      By = by;
+      UsageSince = usageSince;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Container.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Container.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Container.cs	(revision 16892)
@@ -0,0 +1,162 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// A container holds a variable amount of a single continuous entity, e.g. water, coal, grain, etc.
+  /// 
+  /// Put and Get are in FIFO order only when they can be satisfied.
+  /// Any put or get that can be satisfied takes precedence.
+  /// Put events that attempt to add more to the Container than there is capacity for and
+  /// Get events that remove more than there is are backlogged.
+  /// </summary>
+  public class Container {
+
+    public double Capacity { get; protected set; }
+
+    public double Level { get; protected set; }
+
+    protected Simulation Environment { get; private set; }
+
+    protected Queue<ContainerPut> PutQueue { get; private set; }
+    protected Queue<ContainerGet> GetQueue { get; private set; }
+    protected SimplePriorityQueue<Event, double> WhenAtLeastQueue { get; private set; }
+    protected SimplePriorityQueue<Event, double> WhenAtMostQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public Container(Simulation environment, double capacity = double.MaxValue, double initial = 0) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      if (initial < 0) throw new ArgumentException("Initial must be >= 0", "initial");
+      if (initial > capacity) throw new ArgumentException("Initial must be <= capacity", "initial");
+      Environment = environment;
+      Capacity = capacity;
+      Level = initial;
+      PutQueue = new Queue<ContainerPut>();
+      GetQueue = new Queue<ContainerGet>();
+      WhenAtLeastQueue = new SimplePriorityQueue<Event, double>();
+      WhenAtMostQueue = new SimplePriorityQueue<Event, double>(new ReverseComparer<double>());
+      WhenChangeQueue = new List<Event>();
+    }
+
+    public virtual ContainerPut Put(double amount) {
+      if (amount > Capacity) throw new ArgumentException("Cannot put more than capacity", "amount");
+      var put = new ContainerPut(Environment, TriggerGet, amount);
+      PutQueue.Enqueue(put);
+      TriggerPut();
+      return put;
+    }
+
+    public virtual ContainerGet Get(double amount) {
+      if (amount > Capacity) throw new ArgumentException("Cannot get more than capacity", "amount");
+      var get = new ContainerGet(Environment, TriggerPut, amount);
+      GetQueue.Enqueue(get);
+      TriggerGet();
+      return get;
+    }
+
+    public virtual Event WhenAtLeast(double level) {
+      var whenAtLeast = new Event(Environment);
+      WhenAtLeastQueue.Enqueue(whenAtLeast, level);
+      TriggerWhenAtLeast();
+      return whenAtLeast;
+    }
+
+    public virtual Event WhenFull() {
+      return WhenAtLeast(Capacity);
+    }
+
+    public virtual Event WhenAtMost(double level) {
+      var whenAtMost = new Event(Environment);
+      WhenAtMostQueue.Enqueue(whenAtMost, level);
+      TriggerWhenAtMost();
+      return whenAtMost;
+    }
+
+    public virtual Event WhenEmpty() {
+      return WhenAtMost(0);
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected virtual void DoPut(ContainerPut put) {
+      if (Capacity - Level >= put.Amount) {
+        Level += put.Amount;
+        put.Succeed();
+      }
+    }
+
+    protected virtual void DoGet(ContainerGet get) {
+      if (Level >= get.Amount) {
+        Level -= get.Amount;
+        get.Succeed();
+      }
+    }
+
+    protected virtual void TriggerPut(Event @event = null) {
+      while (PutQueue.Count > 0) {
+        var put = PutQueue.Peek();
+        DoPut(put);
+        if (put.IsTriggered) {
+          PutQueue.Dequeue();
+          TriggerWhenAtLeast();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerGet(Event @event = null) {
+      while (GetQueue.Count > 0) {
+        var get = GetQueue.Peek();
+        DoGet(get);
+        if (get.IsTriggered) {
+          GetQueue.Dequeue();
+          TriggerWhenAtMost();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerWhenAtLeast() {
+      while (WhenAtLeastQueue.Count > 0 && Level >= WhenAtLeastQueue.Peek) {
+        var whenAtLeast = WhenAtLeastQueue.Dequeue();
+        whenAtLeast.Succeed();
+      }
+    }
+
+    protected virtual void TriggerWhenAtMost() {
+      while (WhenAtMostQueue.Count > 0 && Level <= WhenAtMostQueue.Peek) {
+        var whenAtMost = WhenAtMostQueue.Dequeue();
+        whenAtMost.Succeed();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerGet.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerGet.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerGet.cs	(revision 16892)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class ContainerGet : Event {
+    public double Amount { get; protected set; }
+    public DateTime Time { get; private set; }
+    public Process Owner { get; set; }
+
+    public ContainerGet(Simulation environment, Action<Event> callback, double amount)
+      : base(environment) {
+      if (amount <= 0) throw new ArgumentException("Amount must be > 0.", "amount");
+      Amount = amount;
+      CallbackList.Add(callback);
+      Time = environment.Now;
+      Owner = environment.ActiveProcess;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerPut.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerPut.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerPut.cs	(revision 16892)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class ContainerPut : Event {
+    public double Amount { get; protected set; }
+    public DateTime Time { get; private set; }
+    public Process Owner { get; set; }
+
+    public ContainerPut(Simulation environment, Action<Event> callback, double amount)
+      : base(environment) {
+      if (amount <= 0) throw new ArgumentException("Amount must be > 0.", "amount");
+      Amount = amount;
+      CallbackList.Add(callback);
+      Time = environment.Now;
+      Owner = environment.ActiveProcess;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/FilterStoreGet.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/FilterStoreGet.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/FilterStoreGet.cs	(revision 16892)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class FilterStoreGet : StoreGet {
+    public Func<object, bool> Filter { get; private set; }
+
+    public FilterStoreGet(Simulation environment, Action<Event> callback, Func<object, bool> filter)
+      : base(environment, callback) {
+      Filter = filter;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/PreemptiveRequest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/PreemptiveRequest.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/PreemptiveRequest.cs	(revision 16892)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public sealed class PreemptiveRequest : Request, IComparable<PreemptiveRequest>, IComparable {
+    public double Priority { get; private set; }
+    public bool Preempt { get; private set; }
+    public bool IsPreempted { get; internal set; }
+
+    public PreemptiveRequest(Simulation environment, Action<Event> callback, Action<Event> disposeCallback, double priority = 1, bool preempt = false)
+      : base(environment, callback, disposeCallback) {
+      Priority = priority;
+      Preempt = preempt;
+    }
+
+    public int CompareTo(PreemptiveRequest other) {
+      if (Priority > other.Priority) return 1;
+      else if (Priority < other.Priority) return -1;
+      if (Time > other.Time) return 1;
+      else if (Time < other.Time) return -1;
+      if (!Preempt && other.Preempt) return 1;
+      else if (Preempt && !other.Preempt) return -1;
+      return 0;
+    }
+
+    public int CompareTo(object obj) {
+      if (obj is PreemptiveRequest other) return CompareTo(other);
+      if (obj == null) return 1;
+      throw new ArgumentException("Can only compare to other objects of type PreemptiveRequest");
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Release.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Release.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Release.cs	(revision 16892)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public sealed class Release : Event {
+    public Request Request { get; private set; }
+
+    public Release(Simulation environment, Request request, Action<Event> callback)
+      : base(environment) {
+      Request = request;
+      CallbackList.Add(callback);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Request.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Request.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Request.cs	(revision 16892)
@@ -0,0 +1,39 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class Request : Event, IDisposable {
+    private readonly Action<Event> disposeCallback;
+    public DateTime Time { get; private set; }
+    public Process Owner { get; set; }
+
+    public Request(Simulation environment, Action<Event> callback, Action<Event> disposeCallback)
+      : base(environment) {
+      CallbackList.Add(callback);
+      this.disposeCallback = disposeCallback;
+      Time = environment.Now;
+      Owner = environment.ActiveProcess;
+    }
+
+    public virtual void Dispose() {
+      if (disposeCallback != null) disposeCallback(this);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ResourcePoolRequest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ResourcePoolRequest.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ResourcePoolRequest.cs	(revision 16892)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class ResourcePoolRequest : Request {
+    public Func<object, bool> Filter { get; private set; }
+
+    public ResourcePoolRequest(Simulation environment, Action<Event> callback, Action<Event> disposeCallback, Func<object, bool> filter)
+      : base(environment, callback, disposeCallback) {
+      Filter = filter;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StoreGet.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StoreGet.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StoreGet.cs	(revision 16892)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class StoreGet : Event {
+    public DateTime Time { get; private set; }
+    public Process Owner { get; set; }
+
+    public StoreGet(Simulation environment, Action<Event> callback)
+      : base(environment) {
+      CallbackList.Add(callback);
+      Time = environment.Now;
+      Owner = environment.ActiveProcess;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StorePut.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StorePut.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StorePut.cs	(revision 16892)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class StorePut : Event {
+    public DateTime Time { get; private set; }
+    public Process Owner { get; set; }
+
+    public StorePut(Simulation environment, Action<Event> callback, object value)
+      : base(environment) {
+      if (value == null) throw new ArgumentNullException("value", "Value to put in a Store cannot be null.");
+      CallbackList.Add(callback);
+      Value = value;
+      Time = environment.Now;
+      Owner = environment.ActiveProcess;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/FilterStore.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/FilterStore.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/FilterStore.cs	(revision 16892)
@@ -0,0 +1,217 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SimSharp {
+  /// <summary>
+  /// A filter store is similar to a <see cref="Store"/>.
+  /// However, in Get it is possible to specify the property of the item wished to retrieve.
+  /// 
+  /// FilterStore holds a variable number of individual items.
+  /// Put are always performed in FIFO order. 
+  /// Get are performed in FIFO order only when they match at least one item in the store.
+  /// </summary>
+  public class FilterStore {
+    protected static readonly Func<object, bool> TrueFunc = _ => true;
+
+    public int Capacity { get; protected set; }
+
+    public int Count { get { return Items.Count; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected Queue<StorePut> PutQueue { get; private set; }
+    protected LinkedList<FilterStoreGet> GetQueue { get; private set; }
+    protected List<object> Items { get; private set; }
+    protected List<Event> WhenNewQueue { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public FilterStore(Simulation environment, int capacity = int.MaxValue) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      PutQueue = new Queue<StorePut>();
+      GetQueue = new LinkedList<FilterStoreGet>();
+      Items = new List<object>();
+      WhenNewQueue = new List<Event>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+    public FilterStore(Simulation environment, IEnumerable<object> items, int capacity = int.MaxValue) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      PutQueue = new Queue<StorePut>();
+      GetQueue = new LinkedList<FilterStoreGet>();
+      Items = new List<object>(items);
+      WhenNewQueue = new List<Event>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
+    }
+
+    public virtual bool IsAvailable(Func<object, bool> filter) {
+      return Items.Any(filter);
+    }
+
+    public virtual StorePut Put(object item) {
+      var put = new StorePut(Environment, TriggerGet, item);
+      PutQueue.Enqueue(put);
+      TriggerPut();
+      return put;
+    }
+
+    public virtual FilterStoreGet Get(Func<object, bool> filter = null) {
+      var get = new FilterStoreGet(Environment, TriggerPut, filter ?? TrueFunc);
+      GetQueue.AddLast(get);
+      TriggerGet();
+      return get;
+    }
+
+    public virtual Event WhenNew() {
+      var whenNew = new Event(Environment);
+      WhenNewQueue.Add(whenNew);
+      return whenNew;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected virtual void DoPut(StorePut put) {
+      if (Items.Count < Capacity) {
+        Items.Add(put.Value);
+        put.Succeed();
+      }
+    }
+
+    protected virtual void DoGet(FilterStoreGet get) {
+      for (int i = 0; i < Items.Count; i++) {
+        var item = Items[i];
+        if (!get.Filter(item)) continue;
+        Items.RemoveAt(i);
+        get.Succeed(item);
+        return;
+      }
+    }
+
+    protected virtual void TriggerPut(Event @event = null) {
+      while (PutQueue.Count > 0) {
+        var put = PutQueue.Peek();
+        DoPut(put);
+        if (put.IsTriggered) {
+          PutQueue.Dequeue();
+          TriggerWhenNew();
+          TriggerWhenAny();
+          TriggerWhenFull();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerGet(Event @event = null) {
+      var current = GetQueue.First;
+      while (current != null) {
+        var get = current.Value;
+        DoGet(get);
+        if (get.IsTriggered) {
+          var next = current.Next;
+          GetQueue.Remove(current);
+          current = next;
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else current = current.Next;
+        if (Items.Count == 0) break;
+      }
+    }
+
+    protected virtual void TriggerWhenNew() {
+      if (WhenNewQueue.Count == 0) return;
+      foreach (var evt in WhenNewQueue)
+        evt.Succeed();
+      WhenNewQueue.Clear();
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Items.Count > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (Count == Capacity) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Count == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PreemptiveResource.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PreemptiveResource.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PreemptiveResource.cs	(revision 16892)
@@ -0,0 +1,204 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SimSharp {
+  /// <summary>
+  /// A PreemptiveResource is similar to a <see cref="PriorityResource"/>. However,
+  /// it may be possible to interrupt a lower-priority user and hand over the resource.
+  /// 
+  /// PreemptiveResource holds a fixed amount of anonymous entities.
+  /// Requests are processed in this order: priority, time, preemption, and finally FIFO.
+  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
+  /// </summary>
+  /// <remarks>
+  /// Working with PreemptiveResource, a process holding a request must always call
+  /// <see cref="Process.HandleFault"/> after yielding an event and handle a potential
+  /// interruption.
+  /// </remarks>
+  public class PreemptiveResource {
+
+    public int Capacity { get; protected set; }
+
+    public int InUse { get { return Users.Count; } }
+
+    public int Remaining { get { return Capacity - InUse; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected SimplePriorityQueue<PreemptiveRequest> RequestQueue { get; private set; }
+    protected Queue<Release> ReleaseQueue { get; private set; }
+    protected HashSet<PreemptiveRequest> Users { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public PreemptiveResource(Simulation environment, int capacity = 1) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0.", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      RequestQueue = new SimplePriorityQueue<PreemptiveRequest>();
+      ReleaseQueue = new Queue<Release>();
+      Users = new HashSet<PreemptiveRequest>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+
+    public virtual PreemptiveRequest Request(double priority = 1, bool preempt = false) {
+      var request = new PreemptiveRequest(Environment, TriggerRelease, DisposeCallback, priority, preempt);
+      RequestQueue.Enqueue(request);
+      TriggerRequest();
+      return request;
+    }
+
+    public virtual Release Release(PreemptiveRequest request) {
+      var release = new Release(Environment, request, TriggerRequest);
+      ReleaseQueue.Enqueue(release);
+      TriggerRelease();
+      return release;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected void DisposeCallback(Event @event) {
+      var request = @event as PreemptiveRequest;
+      if (request != null) Release(request);
+    }
+
+    protected virtual void DoRequest(PreemptiveRequest request) {
+      if (Users.Count >= Capacity && request.Preempt) {
+        // Check if we can preempt another process
+        // MaxItems are the least important according to priorty, time, and preemption flag
+        var preempt = Users.MaxItems(x => x).Last();
+        if (preempt.CompareTo(request) > 0) {
+          preempt.IsPreempted = true;
+          Users.Remove(preempt);
+          preempt.Owner?.Interrupt(new Preempted(request.Owner, preempt.Time));
+        }
+      }
+      if (Users.Count < Capacity) {
+        Users.Add(request);
+        request.Succeed();
+      }
+    }
+
+    protected virtual void DoRelease(Release release) {
+      var req = (PreemptiveRequest)release.Request;
+      if (!Users.Remove(req) && !req.IsPreempted)
+        throw new InvalidOperationException("Released request does not have a user.");
+      release.Succeed();
+    }
+
+    protected virtual void TriggerRequest(Event @event = null) {
+      while (RequestQueue.Count > 0) {
+        var request = RequestQueue.First;
+        DoRequest(request);
+        if (request.IsTriggered) {
+          RequestQueue.Dequeue();
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerRelease(Event @event = null) {
+      while (ReleaseQueue.Count > 0) {
+        var release = ReleaseQueue.Peek();
+        if (release.Request.IsAlive) {
+          if (!RequestQueue.TryRemove((PreemptiveRequest)release.Request))
+            throw new InvalidOperationException("Failed to cancel a request.");
+          release.Succeed();
+          ReleaseQueue.Dequeue();
+        } else {
+          DoRelease(release);
+          if (release.IsTriggered) {
+            ReleaseQueue.Dequeue();
+            TriggerWhenAny();
+            TriggerWhenFull();
+            TriggerWhenChange();
+          } else break;
+        }
+      }
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Remaining > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (InUse == 0) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Remaining == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityResource.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityResource.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityResource.cs	(revision 16892)
@@ -0,0 +1,186 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// A PriorityResource is similar to a <see cref="Resource"/>.
+  /// However, it enables prioritizing requests.
+  /// 
+  /// PriorityResource holds a fixed number of anonymous entities.
+  /// Requests are processed in order priority first, FIFO second.
+  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
+  /// </summary>
+  public class PriorityResource {
+
+    public int Capacity { get; protected set; }
+
+    public int InUse { get { return Users.Count; } }
+
+    public int Remaining { get { return Capacity - InUse; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected SimplePriorityQueue<Request, double> RequestQueue { get; private set; }
+    protected Queue<Release> ReleaseQueue { get; private set; }
+    protected HashSet<Request> Users { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public PriorityResource(Simulation environment, int capacity = 1) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0.", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      RequestQueue = new SimplePriorityQueue<Request, double>();
+      ReleaseQueue = new Queue<Release>();
+      Users = new HashSet<Request>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+
+    public virtual Request Request(double priority = 1) {
+      var request = new Request(Environment, TriggerRelease, DisposeCallback);
+      RequestQueue.Enqueue(request, priority);
+      TriggerRequest();
+      return request;
+    }
+
+    public virtual Release Release(Request request) {
+      var release = new Release(Environment, request, TriggerRequest);
+      ReleaseQueue.Enqueue(release);
+      TriggerRelease();
+      return release;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected void DisposeCallback(Event @event) {
+      var request = @event as Request;
+      if (request != null) Release(request);
+    }
+
+    protected virtual void DoRequest(Request request) {
+      if (Users.Count < Capacity) {
+        Users.Add(request);
+        request.Succeed();
+      }
+    }
+
+    protected virtual void DoRelease(Release release) {
+      if (!Users.Remove(release.Request))
+        throw new InvalidOperationException("Released request does not have a user.");
+      release.Succeed();
+    }
+
+    protected virtual void TriggerRequest(Event @event = null) {
+      while (RequestQueue.Count > 0) {
+        var request = RequestQueue.First;
+        DoRequest(request);
+        if (request.IsTriggered) {
+          RequestQueue.Dequeue();
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerRelease(Event @event = null) {
+      while (ReleaseQueue.Count > 0) {
+        var release = ReleaseQueue.Peek();
+        if (release.Request.IsAlive) {
+          if (!RequestQueue.TryRemove(release.Request))
+            throw new InvalidOperationException("Failed to cancel a request.");
+          release.Succeed();
+          ReleaseQueue.Dequeue();
+        }
+        DoRelease(release);
+        if (release.IsTriggered) {
+          ReleaseQueue.Dequeue();
+          TriggerWhenAny();
+          TriggerWhenFull();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Remaining > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (InUse == 0) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Remaining == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityStore.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityStore.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityStore.cs	(revision 16892)
@@ -0,0 +1,220 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SimSharp {
+  /// <summary>
+  /// A PriorityStore is similar to a <see cref="Store"/>.
+  /// However, items are removed from the store in order of their priority.
+  /// 
+  /// PriorityStore holds a variable number of individual items.
+  /// Put and Get are both processed in strict FIFO order.
+  /// </summary>
+  public class PriorityStore {
+
+    public int Capacity { get; protected set; }
+
+    public int Count { get { return Items.Count; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected Queue<StorePut> PutQueue { get; private set; }
+    protected Queue<StoreGet> GetQueue { get; private set; }
+    protected SimplePriorityQueue<object, double> Items { get; private set; }
+    protected List<Event> WhenNewQueue { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public PriorityStore(Simulation environment, int capacity = int.MaxValue) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      PutQueue = new Queue<StorePut>();
+      GetQueue = new Queue<StoreGet>();
+      Items = new SimplePriorityQueue<object, double>();
+      WhenNewQueue = new List<Event>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+    public PriorityStore(Simulation environment, IEnumerable<object> items, IEnumerable<double> priorities, int capacity = int.MaxValue) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      PutQueue = new Queue<StorePut>();
+      GetQueue = new Queue<StoreGet>();
+      Items = new SimplePriorityQueue<object, double>();
+      var itemsList = items.ToList();
+      foreach (var zip in itemsList.Zip(priorities, (a, b) => new { Item = a, Prio = b }))
+        Items.Enqueue(zip.Item, zip.Prio);
+      if (Items.Count != itemsList.Count) throw new ArgumentException("Fewer priorities than items are given.", "priorities");
+
+      WhenNewQueue = new List<Event>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
+    }
+
+    public virtual StorePut Put(object item, double priority = 1) {
+      var put = new StorePut(Environment, TriggerGet, new PriorityItem(priority, item));
+      PutQueue.Enqueue(put);
+      TriggerPut();
+      return put;
+    }
+
+    public virtual StoreGet Get() {
+      var get = new StoreGet(Environment, TriggerPut);
+      GetQueue.Enqueue(get);
+      TriggerGet();
+      return get;
+    }
+
+    public virtual Event WhenNew() {
+      var whenNew = new Event(Environment);
+      WhenNewQueue.Add(whenNew);
+      return whenNew;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected virtual void DoPut(StorePut put) {
+      if (Items.Count < Capacity) {
+        var pi = (PriorityItem)put.Value;
+        Items.Enqueue(pi.Item, pi.Priority);
+        put.Succeed();
+      }
+    }
+
+    protected virtual void DoGet(StoreGet get) {
+      if (Items.Count > 0) {
+        var item = Items.Dequeue();
+        get.Succeed(item);
+      }
+    }
+
+    protected virtual void TriggerPut(Event @event = null) {
+      while (PutQueue.Count > 0) {
+        var put = PutQueue.Peek();
+        DoPut(put);
+        if (put.IsTriggered) {
+          PutQueue.Dequeue();
+          TriggerWhenNew();
+          TriggerWhenAny();
+          TriggerWhenFull();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerGet(Event @event = null) {
+      while (GetQueue.Count > 0) {
+        var get = GetQueue.Peek();
+        DoGet(get);
+        if (get.IsTriggered) {
+          GetQueue.Dequeue();
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerWhenNew() {
+      if (WhenNewQueue.Count == 0) return;
+      foreach (var evt in WhenNewQueue)
+        evt.Succeed();
+      WhenNewQueue.Clear();
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Items.Count > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (Count == Capacity) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Count == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+
+    protected class PriorityItem {
+      public double Priority { get; protected set; }
+      public object Item { get; protected set; }
+
+      public PriorityItem(double priority, object item) {
+        Priority = priority;
+        Item = item;
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Resource.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Resource.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Resource.cs	(revision 16892)
@@ -0,0 +1,187 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// A resource holds a fixed number of anonymous entities.
+  /// 
+  /// Requests are processed in FIFO order.
+  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
+  /// </summary>
+  public class Resource {
+
+    public int Capacity { get; protected set; }
+
+    public int InUse { get { return Users.Count; } }
+
+    public int Remaining { get { return Capacity - InUse; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected LinkedList<Request> RequestQueue { get; private set; }
+    protected Queue<Release> ReleaseQueue { get; private set; }
+    protected HashSet<Request> Users { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public Resource(Simulation environment, int capacity = 1) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must > 0.", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      RequestQueue = new LinkedList<Request>();
+      ReleaseQueue = new Queue<Release>();
+      Users = new HashSet<Request>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+
+    public virtual Request Request() {
+      var request = new Request(Environment, TriggerRelease, DisposeCallback);
+      RequestQueue.AddLast(request);
+      TriggerRequest();
+      return request;
+    }
+
+    public virtual Release Release(Request request) {
+      var release = new Release(Environment, request, TriggerRequest);
+      ReleaseQueue.Enqueue(release);
+      TriggerRelease();
+      return release;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected virtual void DisposeCallback(Event @event) {
+      var request = @event as Request;
+      if (request != null) {
+        Release(request);
+      }
+    }
+
+    protected virtual void DoRequest(Request request) {
+      if (Users.Count < Capacity) {
+        Users.Add(request);
+        request.Succeed();
+      }
+    }
+
+    protected virtual void DoRelease(Release release) {
+      if (!Users.Remove(release.Request))
+        throw new InvalidOperationException("Released request does not have a user.");
+      release.Succeed();
+    }
+
+    protected virtual void TriggerRequest(Event @event = null) {
+      while (RequestQueue.Count > 0) {
+        var request = RequestQueue.First.Value;
+        DoRequest(request);
+        if (request.IsTriggered) {
+          RequestQueue.RemoveFirst();
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerRelease(Event @event = null) {
+      while (ReleaseQueue.Count > 0) {
+        var release = ReleaseQueue.Peek();
+        if (release.Request.IsAlive) {
+          if (!RequestQueue.Remove(release.Request))
+            throw new InvalidOperationException("Failed to cancel a request.");
+          release.Succeed();
+          ReleaseQueue.Dequeue();
+        } else {
+          DoRelease(release);
+          if (release.IsTriggered) {
+            ReleaseQueue.Dequeue();
+            TriggerWhenAny();
+            TriggerWhenFull();
+            TriggerWhenChange();
+          } else break;
+        }
+      }
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Remaining > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (InUse == 0) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Remaining == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/ResourcePool.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/ResourcePool.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/ResourcePool.cs	(revision 16892)
@@ -0,0 +1,198 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SimSharp {
+  /// <summary>
+  /// A ResourcePool is a crossover between a <see cref="Resource"/> and a <see cref="Store"/>.
+  /// There is a fixed number of non-anonymous resources.
+  /// 
+  /// Requests are performed in FIFO order only when they match at least one resource in the pool.
+  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
+  /// </summary>
+  public class ResourcePool {
+    protected static readonly Func<object, bool> TrueFunc = _ => true;
+
+    public int Capacity { get; protected set; }
+
+    public int InUse { get { return Capacity - Remaining; } }
+
+    public int Remaining { get { return Resources.Count; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected LinkedList<ResourcePoolRequest> RequestQueue { get; private set; }
+    protected Queue<Release> ReleaseQueue { get; private set; }
+    protected List<object> Resources { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public ResourcePool(Simulation environment, IEnumerable<object> resources) {
+      Environment = environment;
+      if (resources == null) throw new ArgumentNullException("resources");
+      Resources = new List<object>(resources);
+      Capacity = Resources.Count;
+      if (Capacity == 0) throw new ArgumentException("There must be at least one resource", "resources");
+      RequestQueue = new LinkedList<ResourcePoolRequest>();
+      ReleaseQueue = new Queue<Release>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+
+    public virtual bool IsAvailable(Func<object, bool> filter) {
+      return Resources.Any(filter);
+    }
+
+    public virtual ResourcePoolRequest Request(Func<object, bool> filter = null) {
+      var request = new ResourcePoolRequest(Environment, TriggerRelease, DisposeCallback, filter ?? TrueFunc);
+      RequestQueue.AddLast(request);
+      TriggerRequest();
+      return request;
+    }
+
+    public virtual Release Release(Request request) {
+      var release = new Release(Environment, request, TriggerRequest);
+      ReleaseQueue.Enqueue(release);
+      TriggerRelease();
+      return release;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected virtual void DisposeCallback(Event @event) {
+      var request = @event as Request;
+      if (request != null) Release(request);
+    }
+
+    protected virtual void DoRequest(ResourcePoolRequest request) {
+      foreach (var o in Resources) {
+        if (!request.Filter(o)) continue;
+        Resources.Remove(o);
+        request.Succeed(o);
+        return;
+      }
+    }
+
+    protected virtual void DoRelease(Release release) {
+      Resources.Add(release.Request.Value);
+      release.Succeed();
+    }
+
+    protected virtual void TriggerRequest(Event @event = null) {
+      var current = RequestQueue.First;
+      while (current != null) {
+        var request = current.Value;
+        DoRequest(request);
+        if (request.IsTriggered) {
+          var next = current.Next;
+          RequestQueue.Remove(current);
+          current = next;
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else current = current.Next;
+        if (Resources.Count == 0) break;
+      }
+    }
+
+    protected virtual void TriggerRelease(Event @event = null) {
+      while (ReleaseQueue.Count > 0) {
+        var release = ReleaseQueue.Peek();
+        if (release.Request.IsAlive) {
+          if (!RequestQueue.Remove((ResourcePoolRequest)release.Request))
+            throw new InvalidOperationException("Failed to cancel a request.");
+          release.Succeed();
+          ReleaseQueue.Dequeue();
+        } else {
+          DoRelease(release);
+          if (release.IsTriggered) {
+            ReleaseQueue.Dequeue();
+            TriggerWhenAny();
+            TriggerWhenFull();
+            TriggerWhenChange();
+          } else break;
+        }
+      }
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Remaining > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (InUse == 0) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Remaining == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Store.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Store.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Store.cs	(revision 16892)
@@ -0,0 +1,203 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace SimSharp {
+  /// <summary>
+  /// The store holds a variable number of individual items.
+  /// The items are removed from the store in FIFO order.
+  /// 
+  /// Put are processed in FIFO order.
+  /// Get are processed in FIFO order.
+  /// </summary>
+  public class Store {
+
+    public int Capacity { get; protected set; }
+
+    public int Count { get { return Items.Count; } }
+
+    protected Simulation Environment { get; private set; }
+
+    protected Queue<StorePut> PutQueue { get; private set; }
+    protected Queue<StoreGet> GetQueue { get; private set; }
+    protected Queue<object> Items { get; private set; }
+    protected List<Event> WhenNewQueue { get; private set; }
+    protected List<Event> WhenAnyQueue { get; private set; }
+    protected List<Event> WhenFullQueue { get; private set; }
+    protected List<Event> WhenEmptyQueue { get; private set; }
+    protected List<Event> WhenChangeQueue { get; private set; }
+
+    public Store(Simulation environment, int capacity = int.MaxValue) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      PutQueue = new Queue<StorePut>();
+      GetQueue = new Queue<StoreGet>();
+      Items = new Queue<object>();
+      WhenNewQueue = new List<Event>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+    }
+    public Store(Simulation environment, IEnumerable<object> items, int capacity = int.MaxValue) {
+      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
+      Environment = environment;
+      Capacity = capacity;
+      PutQueue = new Queue<StorePut>();
+      GetQueue = new Queue<StoreGet>();
+      Items = new Queue<object>(items);
+      WhenNewQueue = new List<Event>();
+      WhenAnyQueue = new List<Event>();
+      WhenFullQueue = new List<Event>();
+      WhenEmptyQueue = new List<Event>();
+      WhenChangeQueue = new List<Event>();
+      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
+    }
+
+    public virtual StorePut Put(object item) {
+      var put = new StorePut(Environment, TriggerGet, item);
+      PutQueue.Enqueue(put);
+      TriggerPut();
+      return put;
+    }
+
+    public virtual StoreGet Get() {
+      var get = new StoreGet(Environment, TriggerPut);
+      GetQueue.Enqueue(get);
+      TriggerGet();
+      return get;
+    }
+
+    public virtual Event WhenNew() {
+      var whenNew = new Event(Environment);
+      WhenNewQueue.Add(whenNew);
+      return whenNew;
+    }
+
+    public virtual Event WhenAny() {
+      var whenAny = new Event(Environment);
+      WhenAnyQueue.Add(whenAny);
+      TriggerWhenAny();
+      return whenAny;
+    }
+
+    public virtual Event WhenFull() {
+      var whenFull = new Event(Environment);
+      WhenFullQueue.Add(whenFull);
+      TriggerWhenFull();
+      return whenFull;
+    }
+
+    public virtual Event WhenEmpty() {
+      var whenEmpty = new Event(Environment);
+      WhenEmptyQueue.Add(whenEmpty);
+      TriggerWhenEmpty();
+      return whenEmpty;
+    }
+
+    public virtual Event WhenChange() {
+      var whenChange = new Event(Environment);
+      WhenChangeQueue.Add(whenChange);
+      return whenChange;
+    }
+
+    protected virtual void DoPut(StorePut put) {
+      if (Items.Count < Capacity) {
+        Items.Enqueue(put.Value);
+        put.Succeed();
+      }
+    }
+
+    protected virtual void DoGet(StoreGet get) {
+      if (Items.Count > 0) {
+        var item = Items.Dequeue();
+        get.Succeed(item);
+      }
+    }
+
+    protected virtual void TriggerPut(Event @event = null) {
+      while (PutQueue.Count > 0) {
+        var put = PutQueue.Peek();
+        DoPut(put);
+        if (put.IsTriggered) {
+          PutQueue.Dequeue();
+          TriggerWhenNew();
+          TriggerWhenAny();
+          TriggerWhenFull();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerGet(Event @event = null) {
+      while (GetQueue.Count > 0) {
+        var get = GetQueue.Peek();
+        DoGet(get);
+        if (get.IsTriggered) {
+          GetQueue.Dequeue();
+          TriggerWhenEmpty();
+          TriggerWhenChange();
+        } else break;
+      }
+    }
+
+    protected virtual void TriggerWhenNew() {
+      if (WhenNewQueue.Count == 0) return;
+      foreach (var evt in WhenNewQueue)
+        evt.Succeed();
+      WhenNewQueue.Clear();
+    }
+
+    protected virtual void TriggerWhenAny() {
+      if (Count > 0) {
+        if (WhenAnyQueue.Count == 0) return;
+        foreach (var evt in WhenAnyQueue)
+          evt.Succeed();
+        WhenAnyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenFull() {
+      if (Count == Capacity) {
+        if (WhenFullQueue.Count == 0) return;
+        foreach (var evt in WhenFullQueue)
+          evt.Succeed();
+        WhenFullQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenEmpty() {
+      if (Count == 0) {
+        if (WhenEmptyQueue.Count == 0) return;
+        foreach (var evt in WhenEmptyQueue)
+          evt.Succeed();
+        WhenEmptyQueue.Clear();
+      }
+    }
+
+    protected virtual void TriggerWhenChange() {
+      if (WhenChangeQueue.Count == 0) return;
+      foreach (var evt in WhenChangeQueue)
+        evt.Succeed();
+      WhenChangeQueue.Clear();
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Properties/AssemblyInfo.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Properties/AssemblyInfo.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Properties/AssemblyInfo.cs	(revision 16892)
@@ -0,0 +1,53 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SimSharp")]
+[assembly: AssemblyDescription("A .NET port of SimPy, discrete event simulation framework")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HEAL")]
+[assembly: AssemblyProduct("SimSharp")]
+[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d51e9cc2-c26b-4df5-94f8-ca8f63f75db9")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.1.1.0")]
+[assembly: AssemblyFileVersion("3.1.1.0")]
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/IRandom.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/IRandom.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/IRandom.cs	(revision 16892)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+namespace SimSharp {
+  public interface IRandom {
+    int Next();
+    int Next(int upperBound);
+    int Next(int lowerBound, int upperBound);
+    double NextDouble();
+
+    void Reinitialise(int seed);
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/Pcg.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/Pcg.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/Pcg.cs	(revision 16892)
@@ -0,0 +1,420 @@
+﻿// MIT License
+// 
+// Copyright (c) 2016 Bismur Studios Ltd.
+// Copyright (c) 2016 Ioannis Giagkiozis
+//
+// This file is part of PCGSharp.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+// and associated documentation files (the "Software"), to deal in the Software without restriction, 
+// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
+// subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all copies or substantial 
+//  portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+//  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 
+//  NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+//  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// This file is based on PCG, the original has the following license: 
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ *       http://www.pcg-random.org
+ */
+
+using System;
+
+// Note, you will see that API is duplicated in PCG and PCGExtended, this is not by accident or 
+// neglect. It would be "cleaner" to have a base class and just implement the core of the generator
+// in derived classes, however, this has a performance cost which for random number generators, in my
+// view, is too high. That said, there is still some room for performance optimisation.
+
+namespace SimSharp {
+
+  /// <summary>
+  /// PCG (Permuted Congruential Generator) is a C# port from C the base PCG generator
+  /// presented in "PCG: A Family of Simple Fast Space-Efficient Statistically Good
+  /// Algorithms for Random Number Generation" by Melissa E. O'Neill. The code follows closely the one 
+  /// made available by O'Neill at her site: http://www.pcg-random.org/download.html
+  /// To understand how exactly this generator works read this:
+  /// http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf 
+  /// </summary>
+  internal class Pcg {
+
+    ulong _state;
+    // This shifted to the left and or'ed with 1ul results in the default increment.
+    const ulong ShiftedIncrement = 721347520444481703ul;
+    ulong _increment = 1442695040888963407ul;
+    const ulong Multiplier = 6364136223846793005ul;
+    const double ToDouble01 = 1.0 / 4294967296.0;
+    
+    public int Next() {
+      uint result = NextUInt();
+      return (int)(result >> 1);
+    }
+
+    public int Next(int maxExclusive) {
+      if (maxExclusive <= 0)
+        throw new ArgumentException("Max Exclusive must be positive");
+
+      uint uMaxExclusive = (uint)(maxExclusive);
+      uint threshold = (uint)(-uMaxExclusive) % uMaxExclusive;
+
+      while (true) {
+        uint result = NextUInt();
+        if (result >= threshold)
+          return (int)(result % uMaxExclusive);
+      }
+    }
+
+    public int Next(int minInclusive, int maxExclusive) {
+      if (maxExclusive <= minInclusive)
+        throw new ArgumentException("MaxExclusive must be larger than MinInclusive");
+
+      uint uMaxExclusive = unchecked((uint)(maxExclusive - minInclusive));
+      uint threshold = (uint)(-uMaxExclusive) % uMaxExclusive;
+
+      while (true) {
+        uint result = NextUInt();
+        if (result >= threshold)
+          return (int)(unchecked((result % uMaxExclusive) + minInclusive));
+      }
+    }
+
+    public int[] NextInts(int count) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new int[count];
+      for (var i = 0; i < count; i++) {
+        resultA[i] = Next();
+      }
+      return resultA;
+    }
+
+    public int[] NextInts(int count, int maxExclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new int[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = Next(maxExclusive);
+      }
+      return resultA;
+    }
+
+    public int[] NextInts(int count, int minInclusive, int maxExclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new int[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = Next(minInclusive, maxExclusive);
+      }
+      return resultA;
+    }
+
+    public uint NextUInt() {
+      ulong oldState = _state;
+      _state = unchecked(oldState * Multiplier + _increment);
+      uint xorShifted = (uint)(((oldState >> 18) ^ oldState) >> 27);
+      int rot = (int)(oldState >> 59);
+      uint result = (xorShifted >> rot) | (xorShifted << ((-rot) & 31));
+      return result;
+    }
+
+    public uint NextUInt(uint maxExclusive) {
+      uint threshold = (uint)(-maxExclusive) % maxExclusive;
+
+      while (true) {
+        uint result = NextUInt();
+        if (result >= threshold)
+          return result % maxExclusive;
+      }
+    }
+
+    public uint NextUInt(uint minInclusive, uint maxExclusive) {
+      if (maxExclusive <= minInclusive)
+        throw new ArgumentException();
+
+      uint diff = (maxExclusive - minInclusive);
+      uint threshold = (uint)(-diff) % diff;
+
+      while (true) {
+        uint result = NextUInt();
+        if (result >= threshold)
+          return (result % diff) + minInclusive;
+      }
+    }
+
+    public uint[] NextUInts(int count) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new uint[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextUInt();
+      }
+      return resultA;
+    }
+
+    public uint[] NextUInts(int count, uint maxExclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new uint[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextUInt(maxExclusive);
+      }
+      return resultA;
+    }
+
+    public uint[] NextUInts(int count, uint minInclusive, uint maxExclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new uint[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextUInt(minInclusive, maxExclusive);
+      }
+      return resultA;
+    }
+
+    public float NextFloat() {
+      return (float)(NextUInt() * ToDouble01);
+    }
+
+    public float NextFloat(float maxInclusive) {
+      if (maxInclusive <= 0)
+        throw new ArgumentException("MaxInclusive must be larger than 0");
+
+      return (float)(NextUInt() * ToDouble01) * maxInclusive;
+    }
+
+    public float NextFloat(float minInclusive, float maxInclusive) {
+      if (maxInclusive < minInclusive)
+        throw new ArgumentException("Max must be larger than min");
+
+      return (float)(NextUInt() * ToDouble01) * (maxInclusive - minInclusive) + minInclusive;
+    }
+
+    public float[] NextFloats(int count) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new float[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextFloat();
+      }
+      return resultA;
+    }
+
+    public float[] NextFloats(int count, float maxInclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new float[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextFloat(maxInclusive);
+      }
+      return resultA;
+    }
+
+    public float[] NextFloats(int count, float minInclusive, float maxInclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new float[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextFloat(minInclusive, maxInclusive);
+      }
+      return resultA;
+    }
+
+    public double NextDouble() {
+      return NextUInt() * ToDouble01;
+    }
+
+    public double NextDouble(double maxInclusive) {
+      if (maxInclusive <= 0)
+        throw new ArgumentException("Max must be larger than 0");
+
+      return NextUInt() * ToDouble01 * maxInclusive;
+    }
+
+    public double NextDouble(double minInclusive, double maxInclusive) {
+      if (maxInclusive < minInclusive)
+        throw new ArgumentException("Max must be larger than min");
+
+      return NextUInt() * ToDouble01 * (maxInclusive - minInclusive) + minInclusive;
+    }
+
+    public double[] NextDoubles(int count) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new double[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextDouble();
+      }
+      return resultA;
+    }
+
+    public double[] NextDoubles(int count, double maxInclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new double[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextDouble(maxInclusive);
+      }
+      return resultA;
+    }
+
+    public double[] NextDoubles(int count, double minInclusive, double maxInclusive) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new double[count];
+      for (int i = 0; i < count; i++) {
+        resultA[i] = NextDouble(minInclusive, maxInclusive);
+      }
+      return resultA;
+    }
+
+    public byte NextByte() {
+      var result = NextUInt();
+      return (byte)(result % 256);
+    }
+
+    public byte[] NextBytes(int count) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new byte[count];
+      for (var i = 0; i < count; i++) {
+        resultA[i] = NextByte();
+      }
+      return resultA;
+    }
+
+    public bool NextBool() {
+      var result = NextUInt();
+      return result % 2 == 1;
+    }
+
+    public bool[] NextBools(int count) {
+      if (count <= 0)
+        throw new ArgumentException("Zero count");
+
+      var resultA = new bool[count];
+      for (var i = 0; i < count; i++) {
+        resultA[i] = NextBool();
+      }
+      return resultA;
+    }
+
+    public int PeriodPow2() {
+      return 64;
+    }
+
+    public void SetStream(int sequence) {
+      SetStream((ulong)sequence);
+    }
+
+    public void SetStream(ulong sequence) {
+      _increment = (sequence << 1) | 1;
+    }
+
+    public ulong CurrentStream() {
+      return _increment >> 1;
+    }
+
+    public Pcg() : this(PcgSeed.GuidBasedSeed()) {
+    }
+
+    public Pcg(int seed) : this((ulong)seed) {
+    }
+
+    public Pcg(int seed, int sequence) : this((ulong)seed, (ulong)sequence) {
+    }
+
+    public Pcg(ulong seed, ulong sequence = ShiftedIncrement) {
+      Initialize(seed, sequence);
+    }
+
+    void Initialize(ulong seed, ulong initseq) {
+      _state = 0ul;
+      SetStream(initseq);
+      NextUInt();
+      _state += seed;
+      NextUInt();
+    }
+
+  }
+
+// MIT License
+// 
+// Copyright (c) 2016 Bismur Studios Ltd.
+// Copyright (c) 2016 Ioannis Giagkiozis
+//
+// This file is part of PCGSharp.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+// and associated documentation files (the "Software"), to deal in the Software without restriction, 
+// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
+// subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all copies or substantial 
+//  portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+//  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 
+//  NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+//  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+  internal static class PcgSeed {
+
+    /// <summary>
+    /// Provides a time-dependent seed value, matching the default behavior of System.Random.
+    /// </summary>
+    public static ulong TimeBasedSeed() {
+      return (ulong)(System.Environment.TickCount);
+    }
+
+    /// <summary>
+    /// Provides a seed based on time and unique GUIDs.
+    /// </summary>
+    public static ulong GuidBasedSeed() {
+      ulong upper = (ulong)(System.Environment.TickCount ^ Guid.NewGuid().GetHashCode()) << 32;
+      ulong lower = (ulong)(System.Environment.TickCount ^ Guid.NewGuid().GetHashCode());
+      return (upper | lower);
+    }
+
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/PcgRandom.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/PcgRandom.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/PcgRandom.cs	(revision 16892)
@@ -0,0 +1,50 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+namespace SimSharp {
+  public class PcgRandom : IRandom {
+    private Pcg pcg;
+
+    public PcgRandom() {
+      pcg = new Pcg();
+    }
+
+    public PcgRandom(int seed) {
+      pcg = new Pcg(seed);
+    }
+    public int Next() {
+      return pcg.Next();
+    }
+
+    public int Next(int upperBound) {
+      return pcg.Next(upperBound);
+    }
+
+    public int Next(int lowerBound, int upperBound) {
+      return pcg.Next(lowerBound, upperBound);
+    }
+
+    public double NextDouble() {
+      return pcg.NextDouble();
+    }
+
+    public void Reinitialise(int seed) {
+      pcg = new Pcg(seed);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/SystemRandom.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/SystemRandom.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/SystemRandom.cs	(revision 16892)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* SimSharp - A .NET port of SimPy, discrete event simulation framework
+Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+
+This program 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.
+
+This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.*/
+#endregion
+
+using System;
+
+namespace SimSharp {
+  public class SystemRandom : IRandom {
+    private Random random;
+
+    public SystemRandom() {
+      random = new Random();
+    }
+
+    public SystemRandom(int seed) {
+      random = new Random(seed);
+    }
+    public int Next() {
+      return random.Next();
+    }
+
+    public int Next(int upperBound) {
+      return random.Next(upperBound);
+    }
+
+    public int Next(int lowerBound, int upperBound) {
+      return random.Next(lowerBound, upperBound);
+    }
+
+    public double NextDouble() {
+      return random.NextDouble();
+    }
+
+    public void Reinitialise(int seed) {
+      random = new Random(seed);
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/SimSharp-3.1.1.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/SimSharp-3.1.1.csproj	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/SimSharp-3.1.1.csproj	(revision 16892)
@@ -0,0 +1,139 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{9FE9C740-7859-4D01-AD07-7D4E15A6320B}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimSharp</RootNamespace>
+    <AssemblyName>SimSharp-3.1.1</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+    <OutputPath>..\..\..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <DocumentationFile>
+    </DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>..\..\..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\..\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>..\..\..\..\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Analysis\ContinuousStatistics.cs" />
+    <Compile Include="Collections\EventQueue.cs" />
+    <Compile Include="Collections\EventQueueNode.cs" />
+    <Compile Include="Collections\Extensions.cs" />
+    <Compile Include="Collections\GenericPriorityQueue.cs" />
+    <Compile Include="Collections\GenericPriorityQueueNode.cs" />
+    <Compile Include="Collections\ReverseComparer.cs" />
+    <Compile Include="Collections\SimplePriorityQueue.cs" />
+    <Compile Include="Core\ActiveObject.cs" />
+    <Compile Include="Core\Events\AnyOf.cs" />
+    <Compile Include="Core\Events\AllOf.cs" />
+    <Compile Include="Core\Resources\Container.cs" />
+    <Compile Include="Core\Environment.cs" />
+    <Compile Include="Core\Resources\Events\ResourcePoolRequest.cs" />
+    <Compile Include="Core\Resources\Events\FilterStoreGet.cs" />
+    <Compile Include="Core\Resources\Events\StorePut.cs" />
+    <Compile Include="Core\Resources\Events\StoreGet.cs" />
+    <Compile Include="Core\Resources\Events\ContainerGet.cs" />
+    <Compile Include="Core\Resources\Events\ContainerPut.cs" />
+    <Compile Include="Core\Events\Condition.cs" />
+    <Compile Include="Core\Events\Event.cs" />
+    <Compile Include="Core\Resources\Events\PreemptiveRequest.cs" />
+    <Compile Include="Core\Events\Process.cs" />
+    <Compile Include="Core\Resources\Events\Release.cs" />
+    <Compile Include="Core\Resources\Events\Request.cs" />
+    <Compile Include="Core\Events\Timeout.cs" />
+    <Compile Include="Core\Exceptions\EmptyScheduleException.cs" />
+    <Compile Include="Core\Preempted.cs" />
+    <Compile Include="Core\Resources\FilterStore.cs" />
+    <Compile Include="Core\Resources\PreemptiveResource.cs" />
+    <Compile Include="Core\Resources\PriorityResource.cs" />
+    <Compile Include="Core\Resources\PriorityStore.cs" />
+    <Compile Include="Core\Resources\Resource.cs" />
+    <Compile Include="Core\Resources\ResourcePool.cs" />
+    <Compile Include="Core\Resources\Store.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Random\IRandom.cs" />
+    <Compile Include="Random\Pcg.cs" />
+    <Compile Include="Random\PcgRandom.cs" />
+    <Compile Include="Random\SystemRandom.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Collections\EventQueue-License.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBubbleChartView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBubbleChartView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionBubbleChartView.cs	(revision 16892)
@@ -24,4 +24,5 @@
 using System.ComponentModel;
 using System.Drawing;
+using System.Globalization;
 using System.Linq;
 using System.Windows.Forms;
@@ -443,4 +444,5 @@
         IntValue intValue = value as IntValue;
         TimeSpanValue timeSpanValue = value as TimeSpanValue;
+        DateTimeValue dateTimeValue = value as DateTimeValue;
         double? ret = null;
         if (doubleValue != null) {
@@ -451,4 +453,6 @@
         else if (timeSpanValue != null) {
           ret = timeSpanValue.Value.TotalSeconds;
+        } else if (dateTimeValue != null) {
+          ret = dateTimeValue.Value.ToOADate();
         } else {
           int columnIndex = Matrix.ColumnNames.ToList().IndexOf(columnName);
@@ -531,9 +535,15 @@
       int axisDimensionCount = Enum.GetNames(typeof(AxisDimension)).Count();
       int columnIndex = xAxisComboBox.SelectedIndex - axisDimensionCount;
-      if (columnIndex >= 0 && Content.GetValue(0, columnIndex) is TimeSpanValue)
-        this.chart.ChartAreas[0].CursorX.Interval = 1;
+      if (columnIndex >= 0) {
+        var value = Content.GetValue(0, columnIndex);
+        if (value is TimeSpanValue || value is DateTimeValue)
+          this.chart.ChartAreas[0].CursorX.Interval = 1;
+      }
       columnIndex = yAxisComboBox.SelectedIndex - axisDimensionCount;
-      if (columnIndex >= 0 && Content.GetValue(0, columnIndex) is TimeSpanValue)
-        this.chart.ChartAreas[0].CursorY.Interval = 1;
+      if (columnIndex >= 0) {
+        var value = Content.GetValue(0, columnIndex);
+        if (value is TimeSpanValue || value is DateTimeValue)
+          this.chart.ChartAreas[0].CursorY.Interval = 1;
+      }
     }
 
@@ -734,4 +744,11 @@
           axis.CustomLabels.Add(i - axis.LabelStyle.Interval / 2, i + axis.LabelStyle.Interval / 2, x);
         }
+      } else if (dimension > 0 && Content.GetValue(0, dimension) is DateTimeValue) {
+        this.chart.ChartAreas[0].RecalculateAxesScale();
+        for (double i = axis.Minimum; i <= axis.Maximum; i += axis.LabelStyle.Interval) {
+          DateTime dt = DateTime.FromOADate(i);
+          string x = dt.ToString(CultureInfo.CurrentCulture);
+          axis.CustomLabels.Add(i - axis.LabelStyle.Interval / 2, i + axis.LabelStyle.Interval / 2, x);
+        }
       }
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs	(revision 16892)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -265,4 +265,5 @@
       this.byTargetTabPage.TabIndex = 0;
       this.byTargetTabPage.Text = "Performance by Target";
+      this.byTargetTabPage.UseVisualStyleBackColor = false;
       // 
       // relativeOrAbsoluteComboBox
@@ -365,4 +366,5 @@
       this.byCostTabPage.TabIndex = 1;
       this.byCostTabPage.Text = "Performance by Cost";
+      this.byCostTabPage.UseVisualStyleBackColor = false;
       // 
       // byCostViewHost
@@ -415,4 +417,5 @@
       this.byTableTabPage.TabIndex = 2;
       this.byTableTabPage.Text = "Expected Runtime Tables";
+      this.byTableTabPage.UseVisualStyleBackColor = false;
       // 
       // ertTableView
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 16892)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -30,4 +31,5 @@
 using HeuristicLab.Analysis;
 using HeuristicLab.Collections;
+using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Core.Views;
@@ -78,4 +80,6 @@
     }
 
+    private List<AlgorithmInstance> groups;
+
     private double[] targets;
     private double[] budgets;
@@ -84,5 +88,6 @@
     private readonly BindingList<ProblemInstance> problems;
 
-    private bool suppressUpdates;
+    private bool updateInProgress;
+    private bool suppressContentEvents;
     private readonly IndexedDataTable<double> byCostDataTable;
     public IndexedDataTable<double> ByCostDataTable {
@@ -94,23 +99,25 @@
       invisibleTargetSeries = new List<Series>();
 
-      targetChart.CustomizeAllChartAreas();
-      targetChart.ChartAreas[0].CursorX.Interval = 1;
-      targetChart.SuppressExceptions = true;
-      byCostDataTable = new IndexedDataTable<double>("ECDF by Cost", "A data table containing the ECDF of function values (relative to best-known).") {
-        VisualProperties = {
-          YAxisTitle = "Proportion of runs",
-          YAxisMinimumFixedValue = 0,
-          YAxisMinimumAuto = false,
-          YAxisMaximumFixedValue = 1,
-          YAxisMaximumAuto = false
-        }
-      };
-      byCostViewHost.Content = byCostDataTable;
-      suppressUpdates = true;
-      relativeOrAbsoluteComboBox.SelectedItem = targetsAreRelative ? "relative" : "absolute";
-      problems = new BindingList<ProblemInstance>();
-      problemComboBox.DataSource = new BindingSource() { DataSource = problems };
-      problemComboBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
-      suppressUpdates = false;
+      try {
+        updateInProgress = true;
+        targetChart.CustomizeAllChartAreas();
+        targetChart.ChartAreas[0].CursorX.Interval = 1;
+        targetChart.SuppressExceptions = true;
+        byCostDataTable = new IndexedDataTable<double>("ECDF by Cost", "A data table containing the ECDF of function values (relative to best-known).") {
+          VisualProperties = {
+            YAxisTitle = "Proportion of runs",
+            YAxisMinimumFixedValue = 0,
+            YAxisMinimumAuto = false,
+            YAxisMaximumFixedValue = 1,
+            YAxisMaximumAuto = false
+          }
+        };
+        byCostViewHost.Content = byCostDataTable;
+
+        relativeOrAbsoluteComboBox.SelectedItem = targetsAreRelative ? "relative" : "absolute";
+        problems = new BindingList<ProblemInstance>();
+        problemComboBox.DataSource = new BindingSource() { DataSource = problems };
+        problemComboBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
+      } finally { updateInProgress = false; }
     }
 
@@ -134,35 +141,45 @@
 
     private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      if (suppressUpdates) return;
+      foreach (var run in e.Items) RegisterRunEvents(run);
+      if (suppressContentEvents) return;
       if (InvokeRequired) {
         Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded), sender, e);
         return;
       }
-      UpdateGroupAndProblemComboBox();
-      UpdateDataTableComboBox();
-      foreach (var run in e.Items)
-        RegisterRunEvents(run);
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        UpdateComboBoxes();
+        GroupRuns();
+      } finally { updateInProgress = false; }
     }
     private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      if (suppressUpdates) return;
+      foreach (var run in e.Items) DeregisterRunEvents(run);
+      if (suppressContentEvents) return;
       if (InvokeRequired) {
         Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved), sender, e);
         return;
       }
-      UpdateGroupAndProblemComboBox();
-      UpdateDataTableComboBox();
-      foreach (var run in e.Items)
-        DeregisterRunEvents(run);
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        UpdateComboBoxes();
+        GroupRuns();
+      } finally { updateInProgress = false; }
     }
     private void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      if (suppressUpdates) return;
+      foreach (var run in e.OldItems) DeregisterRunEvents(run);
+      foreach (var run in e.Items) RegisterRunEvents(run);
+      if (suppressContentEvents) return;
       if (InvokeRequired) {
         Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset), sender, e);
         return;
       }
-      UpdateGroupAndProblemComboBox();
-      UpdateDataTableComboBox();
-      foreach (var run in e.OldItems)
-        DeregisterRunEvents(run);
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        UpdateComboBoxes();
+        GroupRuns();
+      } finally { updateInProgress = false; }
     }
     private void Content_AlgorithmNameChanged(object sender, EventArgs e) {
@@ -176,9 +193,12 @@
         return;
       }
-      suppressUpdates = Content.UpdateOfRunsInProgress;
-      if (!suppressUpdates) {
-        UpdateDataTableComboBox();
-        UpdateGroupAndProblemComboBox();
-        UpdateRuns();
+      suppressContentEvents = Content.UpdateOfRunsInProgress;
+      if (!suppressContentEvents) {
+        if (updateInProgress) return;
+        try {
+          updateInProgress = true;
+          UpdateComboBoxes();
+          GroupRuns();
+        } finally { updateInProgress = false; }
       }
     }
@@ -191,10 +211,15 @@
     }
     private void run_PropertyChanged(object sender, PropertyChangedEventArgs e) {
-      if (suppressUpdates) return;
+      if (suppressContentEvents) return;
       if (InvokeRequired) {
         Invoke((Action<object, PropertyChangedEventArgs>)run_PropertyChanged, sender, e);
       } else {
-        if (e.PropertyName == "Visible")
-          UpdateRuns();
+        if (e.PropertyName == "Visible") {
+          if (updateInProgress) return;
+          try {
+            updateInProgress = true;
+            UpdateRuns();
+          } finally { updateInProgress = false; }
+        }
       }
     }
@@ -213,11 +238,14 @@
       UpdateCaption();
       if (Content != null) {
-        UpdateGroupAndProblemComboBox();
-        UpdateDataTableComboBox();
-      }
-    }
-
-
-    private void UpdateGroupAndProblemComboBox() {
+        try {
+          updateInProgress = true;
+          UpdateComboBoxes();
+          UpdateRuns();
+        } finally { updateInProgress = false; }
+      }
+    }
+
+
+    private void UpdateComboBoxes() {
       var selectedGroupItem = (string)groupComboBox.SelectedItem;
 
@@ -232,35 +260,5 @@
       }
 
-      var table = (string)dataTableComboBox.SelectedItem;
-      var problemDict = CalculateBestTargetPerProblemInstance(table);
-
-      var problemTypesDifferent = problemDict.Keys.Select(x => x.ProblemType).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
-      var problemNamesDifferent = problemDict.Keys.Select(x => x.ProblemName).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
-      var evaluatorDifferent = problemDict.Keys.Select(x => x.Evaluator).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
-      var maximizationDifferent = problemDict.Keys.Select(x => x.Maximization).Distinct().Count() > 1;
-      var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent && !maximizationDifferent;
-
-      var selectedProblemItem = (ProblemInstance)problemComboBox.SelectedItem;
-      problemComboBox.DataSource = null;
-      problemComboBox.Items.Clear();
-      problems.Clear();
-      problems.Add(ProblemInstance.MatchAll);
-      problemComboBox.DataSource = new BindingSource() { DataSource = problems };
-      problemComboBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
-      if (problems[0].Equals(selectedProblemItem)) problemComboBox.SelectedItem = problems[0];
-      foreach (var p in problemDict.ToList()) {
-        p.Key.BestKnownQuality = p.Value;
-        p.Key.DisplayProblemType = problemTypesDifferent;
-        p.Key.DisplayProblemName = problemNamesDifferent || allEqual;
-        p.Key.DisplayEvaluator = evaluatorDifferent;
-        p.Key.DisplayMaximization = maximizationDifferent;
-        problems.Add(p.Key);
-        if (p.Key.Equals(selectedProblemItem)) problemComboBox.SelectedItem = p.Key;
-      }
-      SetEnabledStateOfControls();
-    }
-
-    private void UpdateDataTableComboBox() {
-      string selectedItem = (string)dataTableComboBox.SelectedItem;
+      string selectedDataTable = (string)dataTableComboBox.SelectedItem;
 
       dataTableComboBox.Items.Clear();
@@ -271,9 +269,22 @@
 
       dataTableComboBox.Items.AddRange(dataTables);
-      if (selectedItem != null && dataTableComboBox.Items.Contains(selectedItem)) {
-        dataTableComboBox.SelectedItem = selectedItem;
+      if (selectedDataTable != null && dataTableComboBox.Items.Contains(selectedDataTable)) {
+        dataTableComboBox.SelectedItem = selectedDataTable;
       } else if (dataTableComboBox.Items.Count > 0) {
         dataTableComboBox.SelectedItem = dataTableComboBox.Items[0];
       }
+
+      var selectedProblemItem = (ProblemInstance)problemComboBox.SelectedItem;
+      
+      UpdateProblemInstances();
+      
+      foreach (var p in problems) {
+        if (p.Equals(selectedProblemItem))
+          problemComboBox.SelectedItem = p;
+      }
+
+      if (selectedProblemItem == null && problems.Count > 1) problemComboBox.SelectedItem = problems[1];
+
+      SetEnabledStateOfControls();
     }
 
@@ -288,24 +299,61 @@
     }
 
-    private IEnumerable<AlgorithmInstance> GroupRuns() {
+    private void GroupRuns() {
+      groups = new List<AlgorithmInstance>();
+
       var table = (string)dataTableComboBox.SelectedItem;
-      if (string.IsNullOrEmpty(table)) yield break;
+      if (string.IsNullOrEmpty(table)) return;
 
       var selectedGroup = (string)groupComboBox.SelectedItem;
-      if (string.IsNullOrEmpty(selectedGroup)) yield break;
+      if (string.IsNullOrEmpty(selectedGroup)) return;
 
       var selectedProblem = (ProblemInstance)problemComboBox.SelectedItem;
-      if (selectedProblem == null) yield break;
-      
-      foreach (var x in (from r in Content
-                         where (selectedGroup == AllInstances || r.Parameters.ContainsKey(selectedGroup))
-                           && selectedProblem.Match(r)
-                           && r.Results.ContainsKey(table)
-                           && r.Visible
-                         let key = selectedGroup == AllInstances ? AllInstances : r.Parameters[selectedGroup].ToString()
-                         group r by key into g
-                         select new AlgorithmInstance(g.Key, g, problems))) {
-        yield return x;
-      }
+      if (selectedProblem == null) return;
+
+      foreach (var alg in from r in Content
+                          where (selectedGroup == AllInstances || r.Parameters.ContainsKey(selectedGroup))
+                            && r.Visible
+                            && selectedProblem.Match(r)
+                          let key = selectedGroup == AllInstances
+                            ? AllInstances : r.Parameters[selectedGroup].ToString()
+                          group r by key into g
+                          select g) {
+        var trials = (from run in alg
+                     from pd in problems.Skip(1) // exclude artificial match all
+                     where pd.Match(run) && run.Results.ContainsKey(table)
+                     let cgraph = run.Results[table] as IndexedDataTable<double>
+                     where cgraph != null && cgraph.Rows.Count > 0
+                        && cgraph.Rows.First().Values.Count > 0
+                     group cgraph by pd into g
+                     select g).ToList();
+
+        if (trials.Count == 0) continue;
+        groups.Add(new AlgorithmInstance(alg.Key, trials));
+      }
+    }
+
+    private void UpdateProblemInstances() {
+      try {
+        problems.Clear();
+        var table = (string)dataTableComboBox.SelectedItem;
+        
+        var problemDict = CalculateBestTargetPerProblemInstance(table);
+
+        var problemTypesDifferent = problemDict.Keys.Select(x => x.ProblemType).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
+        var problemNamesDifferent = problemDict.Keys.Select(x => x.ProblemName).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
+        var evaluatorDifferent = problemDict.Keys.Select(x => x.Evaluator).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
+        var maximizationDifferent = problemDict.Keys.Select(x => x.Maximization).Distinct().Count() > 1;
+        var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent && !maximizationDifferent;
+
+        problems.Add(ProblemInstance.MatchAll);
+        foreach (var p in problemDict.OrderBy(x => x.Key.ProblemName, new NaturalStringComparer()).ToList()) {
+          p.Key.BestKnownQuality = p.Value;
+          p.Key.DisplayProblemType = problemTypesDifferent;
+          p.Key.DisplayProblemName = problemNamesDifferent || allEqual;
+          p.Key.DisplayEvaluator = evaluatorDifferent;
+          p.Key.DisplayMaximization = maximizationDifferent;
+          problems.Add(p.Key);
+        }
+      } finally { ((BindingSource)problemComboBox.DataSource).ResetBindings(false); }
     }
 
@@ -321,7 +369,6 @@
 
       if (targets == null) GenerateDefaultTargets();
-
-      var algInstances = GroupRuns().ToList();
-      if (algInstances.Count == 0) return;
+      
+      if (groups.Count == 0) return;
 
       var xAxisTitles = new HashSet<string>();
@@ -337,5 +384,5 @@
       var aggregate = aggregateTargetsCheckBox.Checked;
       double minEff = double.MaxValue, maxEff = double.MinValue;
-      foreach (var alg in algInstances) {
+      foreach (var alg in groups) {
         var noRuns = 0;
         SortedList<double, int> epdfHits = null, epdfMisses = null;
@@ -344,13 +391,12 @@
           misses[alg.Name] = epdfMisses = new SortedList<double, int>();
         }
-        foreach (var problem in alg.GetProblemInstances()) {
-          var max = problem.IsMaximization();
+        foreach (var problem in alg.GetCases().Where(x => x.Maximization.HasValue)) {
+          var max = problem.Maximization.Value;
           var absTargets = GetAbsoluteTargets(problem).ToArray();
-          foreach (var run in alg.GetRuns(problem)) {
+          foreach (var run in alg.GetTrials(problem)) {
             noRuns++;
-            var resultsTable = (IndexedDataTable<double>)run.Results[table];
-            xAxisTitles.Add(resultsTable.VisualProperties.XAxisTitle);
-
-            var efforts = absTargets.Select(t => GetEffortToHitTarget(resultsTable.Rows.First().Values, t, max)).ToArray();
+            xAxisTitles.Add(run.XAxisName);
+
+            var efforts = absTargets.Select(t => GetEffortToHitTarget(run, t, max)).ToArray();
             minEff = Math.Min(minEff, efforts.Min(x => x.Item2));
             maxEff = Math.Max(maxEff, efforts.Max(x => x.Item2));
@@ -391,5 +437,5 @@
       targetChart.ChartAreas[0].CursorY.Interval = 0.05;
 
-      UpdateErtTables(algInstances);
+      UpdateErtTables();
     }
 
@@ -401,5 +447,5 @@
       foreach (var list in hits) {
         var row = new Series(list.Key) {
-          ChartType = SeriesChartType.StepLine,
+          ChartType = list.Value.Count > 1000 ? SeriesChartType.FastLine : SeriesChartType.StepLine,
           BorderWidth = 3,
           Color = colors[colorCount],
@@ -423,5 +469,5 @@
         foreach (var h in list.Value) {
           var prevmissedecdf = missedecdf;
-          while (moreMisses && iter.Current.Key <= h.Key) {
+          while (moreMisses && iter.Current.Key < h.Key) {
             if (!labelPrinted && row.Points.Count > 0) {
               var point = row.Points.Last();
@@ -438,9 +484,6 @@
             if (row.Points.Count > 0 && row.Points.Last().XValue == iter.Current.Key) {
               row.Points.Last().SetValueY(ecdf / movingTargets);
-              row.Points.Last().Color = Color.FromArgb(255 - (int)Math.Floor(255 * (prevmissedecdf / totalTargets)), colors[colorCount]);
             } else {
-              var dp = new DataPoint(iter.Current.Key, ecdf / movingTargets) {
-                Color = Color.FromArgb(255 - (int)Math.Floor(255 * (prevmissedecdf / totalTargets)), colors[colorCount])
-              };
+              var dp = new DataPoint(iter.Current.Key, ecdf / movingTargets);
               if (showMarkers) {
                 dp.MarkerStyle = MarkerStyle.Circle;
@@ -470,9 +513,6 @@
           if (row.Points.Count > 0 && row.Points.Last().XValue == h.Key) {
             row.Points.Last().SetValueY(ecdf / movingTargets);
-            row.Points.Last().Color = Color.FromArgb(255 - (int)Math.Floor(255 * (missedecdf / totalTargets)), colors[colorCount]);
           } else {
-            var dp = new DataPoint(h.Key, ecdf / movingTargets) {
-              Color = Color.FromArgb(255 - (int)Math.Floor(255 * (missedecdf / totalTargets)), colors[colorCount])
-            };
+            var dp = new DataPoint(h.Key, ecdf / movingTargets);
             if (showMarkers) {
               dp.MarkerStyle = MarkerStyle.Circle;
@@ -492,15 +532,15 @@
           // if there are misses beyond the last hit we extend the shaded area
           missedecdf += iter.Current.Value;
-          var dp = new DataPoint(iter.Current.Key, ecdf / movingTargets) {
-            Color = Color.FromArgb(255 - (int)Math.Floor(255 * (missedecdf / totalTargets)), colors[colorCount])
-          };
-          if (showMarkers) {
-            dp.MarkerStyle = MarkerStyle.Circle;
-            dp.MarkerBorderWidth = 1;
-            dp.MarkerSize = 5;
-          }
-          row.Points.Add(dp);
-          if (boundShadingCheckBox.Checked) {
-            rowShade.Points.Add(new DataPoint(iter.Current.Key, new[] {ecdf / totalTargets, (ecdf + missedecdf) / totalTargets}));
+          if (row.Points.Count == 0 || row.Points.Last().XValue < iter.Current.Key) {
+            var dp = new DataPoint(iter.Current.Key, ecdf / movingTargets);
+            if (showMarkers) {
+              dp.MarkerStyle = MarkerStyle.Circle;
+              dp.MarkerBorderWidth = 1;
+              dp.MarkerSize = 5;
+            }
+            row.Points.Add(dp);
+            if (boundShadingCheckBox.Checked) {
+              rowShade.Points.Add(new DataPoint(iter.Current.Key, new[] { ecdf / totalTargets, (ecdf + missedecdf) / totalTargets }));
+            }
           }
           moreMisses = iter.MoveNext();
@@ -517,5 +557,5 @@
         }
 
-        if (!labelPrinted) {
+        if (!labelPrinted && row.Points.Count > 0) {
           var point = row.Points.Last();
           if (showLabelsInTargetChart)
@@ -554,5 +594,7 @@
     private IEnumerable<double> GetAbsoluteTargets(ProblemInstance pInstance) {
       if (!targetsAreRelative) return targets;
-      var maximization = pInstance.IsMaximization();
+      if (!pInstance.Maximization.HasValue) throw new ArgumentException("Problem doesn't specify if it is to be maximized or minimized.");
+
+      var maximization = pInstance.Maximization.Value;
       var bestKnown = pInstance.BestKnownQuality;
       if (double.IsNaN(bestKnown)) throw new ArgumentException("Problem instance does not have a defined best - known quality.");
@@ -570,7 +612,8 @@
 
     private double[] GetAbsoluteTargetsWorstToBest(ProblemInstance pInstance) {
-      if (double.IsNaN(pInstance.BestKnownQuality)) throw new ArgumentException("Problem instance does not have a defined best-known quality.");
+      if (targetsAreRelative && double.IsNaN(pInstance.BestKnownQuality)) throw new ArgumentException("Problem instance does not have a defined best-known quality.");
+      if (!pInstance.Maximization.HasValue) throw new ArgumentException("Problem doesn't specify if it is to be maximized or minimized.");
       var absTargets = GetAbsoluteTargets(pInstance);
-      return (pInstance.IsMaximization()
+      return (pInstance.Maximization.Value
         ? absTargets.OrderBy(x => x) : absTargets.OrderByDescending(x => x)).ToArray();
     }
@@ -582,24 +625,24 @@
 
     private Tuple<bool, double> GetEffortToHitTarget(
-        ObservableList<Tuple<double, double>> convergenceGraph,
+        ConvergenceGraph cgraph,
         double absTarget, bool maximization) {
-      if (convergenceGraph.Count == 0)
+      if (cgraph.Points == 0)
         throw new ArgumentException("Convergence graph is empty.", "convergenceGraph");
       
-      var index = convergenceGraph.BinarySearch(Tuple.Create(0.0, absTarget), new TargetComparer(maximization));
+      var index = cgraph.BinarySearch(new ConvergenceGraphPoint(0.0, absTarget), new TargetComparer(maximization));
       if (index >= 0) {
-        return Tuple.Create(true, convergenceGraph[index].Item1);
+        return Tuple.Create(true, cgraph[index].Runlength);
       } else {
         index = ~index;
-        if (index >= convergenceGraph.Count)
-          return Tuple.Create(false, convergenceGraph.Last().Item1);
-        return Tuple.Create(true, convergenceGraph[index].Item1);
-      }
-    }
-
-    private void UpdateErtTables(List<AlgorithmInstance> algorithmInstances) {
+        if (index >= cgraph.Points)
+          return Tuple.Create(false, cgraph.Last().Runlength);
+        return Tuple.Create(true, cgraph[index].Runlength);
+      }
+    }
+
+    private void UpdateErtTables() {
       ertTableView.Content = null;
       var columns = targets.Length + 1;
-      var totalRows = algorithmInstances.Count * algorithmInstances.Max(x => x.GetNumberOfProblemInstances()) + algorithmInstances.Max(x => x.GetNumberOfProblemInstances());
+      var totalRows = groups.Count * groups.Max(x => x.GetNumberOfCases()) + groups.Max(x => x.GetNumberOfCases());
       var matrix = new StringMatrix(totalRows, columns);
       var rowNames = new List<string>();
@@ -611,9 +654,10 @@
       if (string.IsNullOrEmpty(tableName)) return;
       
-      var problems = algorithmInstances.SelectMany(x => x.GetProblemInstances()).Distinct().ToList();
-
-      foreach (var problem in problems) {
-        var max = problem.IsMaximization();
+      var problems = groups.SelectMany(x => x.GetCases()).Distinct().ToList();
+
+      foreach (var problem in problems.OrderBy(x => x.ProblemName, new NaturalStringComparer())) {
+        if (double.IsNaN(problem.BestKnownQuality) || !problem.Maximization.HasValue) continue;
         rowNames.Add(problem.ToString());
+        var max = problem.Maximization.Value;
         var absTargets = GetAbsoluteTargetsWorstToBest(problem);
         if (targetsAreRelative) {
@@ -625,7 +669,7 @@
         rowCount++;
 
-        foreach (var alg in algorithmInstances) {
+        foreach (var alg in groups) {
           rowNames.Add(alg.Name);
-          var runs = alg.GetRuns(problem).ToList();
+          var runs = alg.GetTrials(problem).ToList();
           if (runs.Count == 0) {
             matrix[rowCount, columns - 1] = "N/A";
@@ -635,5 +679,5 @@
           var result = default(ErtCalculationResult);
           for (var i = 0; i < absTargets.Length; i++) {
-            result = ExpectedRuntimeHelper.CalculateErt(runs, tableName, absTargets[i], max);
+            result = ExpectedRuntimeHelper.CalculateErt(runs.Select(x => x.ToTuples()), absTargets[i], max);
             matrix[rowCount, i] = result.ToString();
           }
@@ -658,19 +702,16 @@
 
       if (budgets == null) GenerateDefaultBudgets(table);
-
-      var algInstances = GroupRuns().ToList();
-      if (algInstances.Count == 0) return;
+      
+      if (groups.Count == 0) return;
 
       var colorCount = 0;
       var lineStyleCount = 0;
       
-      foreach (var alg in algInstances) {
+      foreach (var alg in groups) {
         var hits = new Dictionary<string, SortedList<double, double>>();
 
-        foreach (var problem in alg.GetProblemInstances()) {
-          foreach (var run in alg.GetRuns(problem)) {
-            var resultsTable = (IndexedDataTable<double>)run.Results[table];
-
-            CalculateHitsForEachBudget(hits, resultsTable.Rows.First(), problem, alg.Name);
+        foreach (var problem in alg.GetCases()) {
+          foreach (var run in alg.GetTrials(problem)) {
+            CalculateHitsForEachBudget(hits, run, problem, alg.Name);
           }
         }
@@ -705,7 +746,19 @@
 
     private void GenerateDefaultBudgets(string table) {
-      var runs = Content;
-      var min = runs.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item1).Min()).Min();
-      var max = runs.Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values.Select(y => y.Item1).Max()).Max();
+      var runs = Content.Where(x => x.Results.ContainsKey(table) && x.Results[table] is IndexedDataTable<double>)
+                        .Select(x => (IndexedDataTable<double>)x.Results[table])
+                        .Where(x => x.Rows.Count > 0 && x.Rows.First().Values.Count > 0)
+                        .Select(x => x.Rows.First())
+                        .ToList();
+      if (runs.Count == 0) {
+        budgets = new double[0];
+        suppressBudgetsEvents = true;
+        budgetsTextBox.Text = string.Empty;
+        suppressBudgetsEvents = false;
+        return;
+      }
+
+      var min = runs.Select(x => x.Values.Select(y => y.Item1).Min()).Min();
+      var max = runs.Select(x => x.Values.Select(y => y.Item1).Max()).Max();
       var points = 3;
       budgets = Enumerable.Range(1, points).Select(x => min + (x / (double)points) * (max - min)).ToArray();
@@ -715,17 +768,17 @@
     }
 
-    private void CalculateHitsForEachBudget(Dictionary<string, SortedList<double, double>> hits, IndexedDataRow<double> row, ProblemInstance problem, string groupName) {
-      var max = problem.IsMaximization();
+    private void CalculateHitsForEachBudget(Dictionary<string, SortedList<double, double>> hits, ConvergenceGraph cgraph, ProblemInstance problem, string groupName) {
+      var max = problem.Maximization.Value;
       var prevIndex = 0;
       foreach (var b in budgets) {
         var key = groupName + "-" + b;
-        var index = row.Values.BinarySearch(prevIndex, row.Values.Count - prevIndex, Tuple.Create(b, 0.0), new CostComparer());
+        var index = cgraph.BinarySearch(prevIndex, cgraph.Points - prevIndex, new ConvergenceGraphPoint(b, 0.0), new CostComparer());
         if (index < 0) {
           index = ~index;
-          if (index >= row.Values.Count) break; // the run wasn't long enough to use up budget b (or any subsequent larger one)
+          if (index >= cgraph.Points) break; // the run wasn't long enough to use up budget b (or any subsequent larger one)
         }
         if (!hits.ContainsKey(key)) hits.Add(key, new SortedList<double, double>());
-        var v = row.Values[index];
-        var relTgt = CalculateRelativeDifference(max, problem.BestKnownQuality, v.Item2) + 1;
+        var v = cgraph[index];
+        var relTgt = CalculateRelativeDifference(max, problem.BestKnownQuality, v.Quality) + 1;
         if (hits[key].ContainsKey(relTgt))
           hits[key][relTgt]++;
@@ -743,27 +796,36 @@
       if (InvokeRequired) Invoke((Action)SynchronizeTargetTextBox);
       else {
-        suppressTargetsEvents = true;
-        try {
-          if (targetsAreRelative)
-            targetsTextBox.Text = string.Join("% ; ", targets.Select(x => x * 100)) + "%";
-          else targetsTextBox.Text = string.Join(" ; ", targets);
-        } finally { suppressTargetsEvents = false; }
+        if (targetsAreRelative)
+          targetsTextBox.Text = string.Join("% ; ", targets.Select(x => x * 100)) + "%";
+        else targetsTextBox.Text = string.Join(" ; ", targets);
       }
     }
 
     private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
-      UpdateRuns();
-      SetEnabledStateOfControls();
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        UpdateRuns();
+        SetEnabledStateOfControls();
+      } finally { updateInProgress = false; }
     }
     private void problemComboBox_SelectedIndexChanged(object sender, EventArgs e) {
-      UpdateRuns();
-      SetEnabledStateOfControls();
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        UpdateRuns();
+        SetEnabledStateOfControls();
+      } finally { updateInProgress = false; }
     }
     private void dataTableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
-      if (dataTableComboBox.SelectedIndex >= 0)
-        GenerateDefaultBudgets((string)dataTableComboBox.SelectedItem);
-      UpdateBestKnownQualities();
-      UpdateRuns();
-      SetEnabledStateOfControls();
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        if (dataTableComboBox.SelectedIndex >= 0)
+          GenerateDefaultBudgets((string)dataTableComboBox.SelectedItem);
+        UpdateBestKnownQualities();
+        UpdateRuns();
+        SetEnabledStateOfControls();
+      } finally { updateInProgress = false; }
     }
 
@@ -778,63 +840,75 @@
 
     #region Event handlers for target analysis
-    private bool suppressTargetsEvents;
     private void targetsTextBox_Validating(object sender, CancelEventArgs e) {
-      if (suppressTargetsEvents) return;
-      var targetStrings = targetsTextBox.Text.Split(new[] { '%', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
-      var targetList = new List<decimal>();
-      foreach (var ts in targetStrings) {
-        decimal t;
-        if (!decimal.TryParse(ts, out t)) {
-          errorProvider.SetError(targetsTextBox, "Not all targets can be parsed: " + ts);
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        var targetStrings = targetsTextBox.Text.Split(new[] { '%', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+        var targetList = new List<decimal>();
+        foreach (var ts in targetStrings) {
+          decimal t;
+          if (!decimal.TryParse(ts, out t)) {
+            errorProvider.SetError(targetsTextBox, "Not all targets can be parsed: " + ts);
+            e.Cancel = true;
+            return;
+          }
+          if (targetsAreRelative)
+            targetList.Add(t / 100);
+          else targetList.Add(t);
+        }
+        if (targetList.Count == 0) {
+          errorProvider.SetError(targetsTextBox, "Give at least one target value!");
           e.Cancel = true;
           return;
         }
-        if (targetsAreRelative)
-          targetList.Add(t / 100);
-        else targetList.Add(t);
-      }
-      if (targetList.Count == 0) {
-        errorProvider.SetError(targetsTextBox, "Give at least one target value!");
-        e.Cancel = true;
-        return;
-      }
-      e.Cancel = false;
-      errorProvider.SetError(targetsTextBox, null);
-      targets = targetsAreRelative ? targetList.Select(x => (double)x).OrderByDescending(x => x).ToArray() : targetList.Select(x => (double)x).ToArray();
-
-      SynchronizeTargetTextBox();
-      UpdateResultsByTarget();
-      SetEnabledStateOfControls();
+        e.Cancel = false;
+        errorProvider.SetError(targetsTextBox, null);
+        targets = targetsAreRelative ? targetList.Select(x => (double)x).OrderByDescending(x => x).ToArray() : targetList.Select(x => (double)x).ToArray();
+
+        SynchronizeTargetTextBox();
+        UpdateResultsByTarget();
+        SetEnabledStateOfControls();
+
+      } finally { updateInProgress = false; }
     }
 
     private void aggregateTargetsCheckBox_CheckedChanged(object sender, EventArgs e) {
-      SuspendRepaint();
+      if (updateInProgress) return;
       try {
-        UpdateResultsByTarget();
-      } finally { ResumeRepaint(true); }
-    }
-
-    private void relativeOrAbsoluteComboBox_SelectedIndexChanged(object sender, EventArgs e) {
-      if (suppressUpdates) return;
-      var pd = (ProblemInstance)problemComboBox.SelectedItem;
-      if (!double.IsNaN(pd.BestKnownQuality)) {
-        var max = pd.IsMaximization();
-        if (targetsAreRelative) targets = GetAbsoluteTargets(pd).ToArray();
-        else {
-          // Rounding to 5 digits since it's certainly appropriate for this application
-          if (pd.BestKnownQuality > 0) {
-            targets = targets.Select(x => Math.Round(max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
-          } else if (pd.BestKnownQuality < 0) {
-            targets = targets.Select(x => Math.Round(!max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
-          }
-        }
-      }
-      targetsAreRelative = (string)relativeOrAbsoluteComboBox.SelectedItem == "relative";
-      SynchronizeTargetTextBox();
-
-      try {
+        updateInProgress = true;
         SuspendRepaint();
         UpdateResultsByTarget();
-      } finally { ResumeRepaint(true); }
+      } finally {
+        updateInProgress = false;
+        ResumeRepaint(true);
+      }
+    }
+
+    private void relativeOrAbsoluteComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+      if (updateInProgress) return;
+      try {
+        updateInProgress = true;
+        var pd = (ProblemInstance)problemComboBox.SelectedItem;
+        if (!double.IsNaN(pd.BestKnownQuality) && pd.Maximization.HasValue) {
+          var max = pd.Maximization.Value;
+          if (targetsAreRelative) targets = GetAbsoluteTargets(pd).ToArray();
+          else {
+            // Rounding to 5 digits since it's certainly appropriate for this application
+            if (pd.BestKnownQuality > 0) {
+              targets = targets.Select(x => Math.Round(max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
+            } else if (pd.BestKnownQuality < 0) {
+              targets = targets.Select(x => Math.Round(!max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
+            }
+          }
+        }
+        targetsAreRelative = (string)relativeOrAbsoluteComboBox.SelectedItem == "relative";
+        SynchronizeTargetTextBox();
+        
+        SuspendRepaint();
+        UpdateResultsByTarget();
+      } finally {
+        updateInProgress = false;
+        ResumeRepaint(true);
+      }
     }
 
@@ -856,7 +930,10 @@
               : dialog.Values.Select(x => (double)x).ToArray();
 
-            SynchronizeTargetTextBox();
-            UpdateResultsByTarget();
-            SetEnabledStateOfControls();
+            try {
+              updateInProgress = true;
+              SynchronizeTargetTextBox();
+              UpdateResultsByTarget();
+              SetEnabledStateOfControls();
+            } finally { updateInProgress = false; }
           }
         }
@@ -869,16 +946,20 @@
       
       foreach (var run in Content) {
-        if (!run.Results.ContainsKey(table)) continue;
+        if (!run.Results.ContainsKey(table) || !(run.Results[table] is IndexedDataTable<double>)) continue;
         var resultsTable = (IndexedDataTable<double>)run.Results[table];
         var values = resultsTable.Rows.First().Values;
         var pd = new ProblemInstance(run);
+        if (!pd.Maximization.HasValue) continue;
         pd = problems.Single(x => x.Equals(pd));
-        var max = pd.IsMaximization();
+        if (targetsAreRelative && double.IsNaN(pd.BestKnownQuality)) continue;
+
+        var max = pd.Maximization.Value;
         var absTargets = GetAbsoluteTargetsWorstToBest(pd);
+        var cgraph = new ConvergenceGraph(resultsTable, max);
 
         var prevIndex = 0;
         for (var i = 0; i < absTargets.Length; i++) {
           var absTarget = absTargets[i];
-          var index = values.BinarySearch(prevIndex, values.Count - prevIndex, Tuple.Create(0.0, absTarget), new TargetComparer(max));
+          var index = cgraph.BinarySearch(prevIndex, values.Count - prevIndex, new ConvergenceGraphPoint(0.0, absTarget), new TargetComparer(max));
           if (index < 0) {
             index = ~index;
@@ -893,16 +974,24 @@
 
     private void markerCheckBox_CheckedChanged(object sender, EventArgs e) {
-      SuspendRepaint();
       try {
+        updateInProgress = true;
+        SuspendRepaint();
         UpdateResultsByTarget();
-      } finally { ResumeRepaint(true); }
+      } finally {
+        updateInProgress = false;
+        ResumeRepaint(true);
+      }
     }
 
     private void showLabelsCheckBox_CheckedChanged(object sender, EventArgs e) {
       showLabelsInTargetChart = showLabelsCheckBox.Checked;
-      SuspendRepaint();
       try {
+        updateInProgress = true;
+        SuspendRepaint();
         UpdateResultsByTarget();
-      } finally { ResumeRepaint(true); }
+      } finally {
+        updateInProgress = false;
+        ResumeRepaint(true);
+      }
     }
     #endregion
@@ -976,9 +1065,11 @@
         var values = resultsTable.Rows.First().Values;
         var pd = new ProblemInstance(run);
+        if (!pd.Maximization.HasValue) continue;
         pd = problems.Single(x => x.Equals(pd));
-
+        var max = pd.Maximization.Value;
+        var cgraph = new ConvergenceGraph(resultsTable, max);
         var prevIndex = 0;
         foreach (var b in budgets) {
-          var index = values.BinarySearch(prevIndex, values.Count - prevIndex, Tuple.Create(b, 0.0), new CostComparer());
+          var index = cgraph.BinarySearch(prevIndex, values.Count - prevIndex, new ConvergenceGraphPoint(b, 0.0), new CostComparer());
           if (index < 0) {
             index = ~index;
@@ -986,5 +1077,5 @@
           }
           var v = values[index];
-          var tgt = targetsAreRelative ? CalculateRelativeDifference(pd.IsMaximization(), pd.BestKnownQuality, v.Item2) : v.Item2;
+          var tgt = targetsAreRelative ? CalculateRelativeDifference(max, pd.BestKnownQuality, v.Item2) : v.Item2;
           run.Results[table + (targetsAreRelative ? ".CostForRelTarget " : ".CostForAbsTarget ") + b] = new DoubleValue(tgt);
           prevIndex = index;
@@ -1011,16 +1102,35 @@
     private Dictionary<ProblemInstance, double> CalculateBestTargetPerProblemInstance(string table) {
       if (table == null) table = string.Empty;
-      return (from r in Content
-              where r.Visible
-              let pd = new ProblemInstance(r)
-              let target = r.Parameters.ContainsKey("BestKnownQuality")
-                           && r.Parameters["BestKnownQuality"] is DoubleValue
-                ? ((DoubleValue)r.Parameters["BestKnownQuality"]).Value
-                : (r.Results.ContainsKey(table) && r.Results[table] is IndexedDataTable<double>
-                  ? ((IndexedDataTable<double>)r.Results[table]).Rows.First().Values.Last().Item2
-                  : double.NaN)
-              group target by pd into g
-              select new { Problem = g.Key, Target = g.Any(x => !double.IsNaN(x)) ? (g.Key.IsMaximization() ? g.Max() : g.Where(x => !double.IsNaN(x)).Min()) : double.NaN })
-        .ToDictionary(x => x.Problem, x => x.Target);
+      var dict = new Dictionary<ProblemInstance, double>();
+      foreach (var k in from r in Content where r.Visible let pd = new ProblemInstance(r) group r by pd into g select new { Problem = g.Key, Runs = g.ToList() }) {
+        var pd = k.Problem;
+        if (!pd.Maximization.HasValue) continue;
+        var values = GetQualityValues(k.Runs, table).ToList();
+        var target = double.NaN;
+        if (values.Count > 0) {
+          target = pd.Maximization.Value ? values.Max() : values.Min();
+        }
+        dict[pd] = target;
+      }
+      return dict;
+    }
+
+    private IEnumerable<double> GetQualityValues(List<IRun> runs, string table) {
+      foreach (var r in runs) {
+        IItem item;
+        if (r.Parameters.TryGetValue("BestKnownQuality", out item)) {
+          var dval = item as DoubleValue;
+          if (dval != null && !double.IsNaN(dval.Value))
+            yield return dval.Value;
+        }
+        if (r.Results.TryGetValue(table, out item)) {
+          var dt = item as IndexedDataTable<double>;
+          if (dt != null && dt.Rows.Count > 0 && dt.Rows.First().Values.Count > 0) {
+            var last = dt.Rows.First().Values.Last().Item2;
+            if (!double.IsNaN(last))
+              yield return Math.Round(last, 10);
+          }
+        }
+      }
     }
 
@@ -1032,4 +1142,5 @@
       SuspendRepaint();
       try {
+        GroupRuns();
         UpdateResultsByTarget();
         UpdateResultsByCost();
@@ -1136,4 +1247,5 @@
     }
 
+    #region Helper classes
     private class AlgorithmInstance : INotifyPropertyChanged {
       private string name;
@@ -1147,42 +1259,40 @@
       }
 
-      private Dictionary<ProblemInstance, List<IRun>> performanceData;
-
-      public int GetNumberOfProblemInstances() {
+      private Dictionary<ProblemInstance, List<ConvergenceGraph>> performanceData;
+
+      public int GetNumberOfCases() {
         return performanceData.Count;
       }
 
-      public IEnumerable<ProblemInstance> GetProblemInstances() {
+      public IEnumerable<ProblemInstance> GetCases() {
         return performanceData.Keys;
       }
 
-      public int GetNumberOfRuns(ProblemInstance p) {
+      public int GetNumberOfTrials(ProblemInstance p) {
         if (p == ProblemInstance.MatchAll) return performanceData.Select(x => x.Value.Count).Sum();
-        List<IRun> runs;
-        if (performanceData.TryGetValue(p, out runs))
-          return runs.Count;
+        List<ConvergenceGraph> trials;
+        if (performanceData.TryGetValue(p, out trials))
+          return trials.Count;
 
         return 0;
       }
 
-      public IEnumerable<IRun> GetRuns(ProblemInstance p) {
+      public IEnumerable<ConvergenceGraph> GetTrials(ProblemInstance p) {
         if (p == ProblemInstance.MatchAll) return performanceData.SelectMany(x => x.Value);
-        List<IRun> runs;
-        if (performanceData.TryGetValue(p, out runs))
-          return runs;
-
-        return Enumerable.Empty<IRun>();
-      }
-
-      public AlgorithmInstance(string name, IEnumerable<IRun> runs, IEnumerable<ProblemInstance> problems) {
+        List<ConvergenceGraph> trials;
+        if (performanceData.TryGetValue(p, out trials))
+          return trials;
+
+        return Enumerable.Empty<ConvergenceGraph>();
+      }
+
+      public AlgorithmInstance(string name, IEnumerable<IGrouping<ProblemInstance, IndexedDataTable<double>>> trials) {
         this.name = name;
 
-        var pDict = problems.ToDictionary(r => r, _ => new List<IRun>());
-        foreach (var y in runs) {
-          var pd = new ProblemInstance(y);
-          List<IRun> l;
-          if (pDict.TryGetValue(pd, out l)) l.Add(y);
-        }
-        performanceData = pDict.Where(x => x.Value.Count > 0).ToDictionary(x => x.Key, x => x.Value);
+        performanceData = new Dictionary<ProblemInstance, List<ConvergenceGraph>>();
+        foreach (var t in trials) {
+          if (double.IsNaN(t.Key.BestKnownQuality) || !t.Key.Maximization.HasValue) continue;
+          performanceData[t.Key] = t.Select(c => new ConvergenceGraph(c, t.Key.Maximization.Value)).ToList();
+        }
       }
 
@@ -1214,5 +1324,5 @@
         ProblemName = string.Empty;
         Evaluator = string.Empty;
-        Maximization = string.Empty;
+        Maximization = null;
         DisplayProblemType = false;
         DisplayProblemName = false;
@@ -1227,9 +1337,9 @@
         ProblemName = GetStringValueOrEmpty(run, "Problem Name");
         Evaluator = GetStringValueOrEmpty(run, "Evaluator");
-        Maximization = GetMaximizationValueOrEmpty(run, "Maximization");
+        Maximization = GetBoolValueOrEmpty(run, "Maximization");
         DisplayProblemType = !string.IsNullOrEmpty(ProblemType);
         DisplayProblemName = !string.IsNullOrEmpty(ProblemName);
         DisplayEvaluator = !string.IsNullOrEmpty(Evaluator);
-        DisplayMaximization = !string.IsNullOrEmpty(Maximization);
+        DisplayMaximization = Maximization.HasValue;
         matchAll = false;
         BestKnownQuality = GetDoubleValueOrNaN(run, "BestKnownQuality");
@@ -1299,6 +1409,6 @@
         }
       }
-      private string maximization;
-      public string Maximization {
+      private bool? maximization;
+      public bool? Maximization {
         get { return maximization; }
         set {
@@ -1318,14 +1428,10 @@
       }
 
-      public bool IsMaximization() {
-        return Maximization == "MAX";
-      }
-
       public bool Match(IRun run) {
         return matchAll ||
-               GetStringValueOrEmpty(run, "Problem Type") == ProblemType
+               (GetStringValueOrEmpty(run, "Problem Type") == ProblemType
                && GetStringValueOrEmpty(run, "Problem Name") == ProblemName
                && GetStringValueOrEmpty(run, "Evaluator") == Evaluator
-               && GetMaximizationValueOrEmpty(run, "Maximization") == Maximization;
+               && GetBoolValueOrEmpty(run, "Maximization") == Maximization);
       }
 
@@ -1348,11 +1454,11 @@
       }
 
-      private string GetMaximizationValueOrEmpty(IRun run, string key) {
+      private bool? GetBoolValueOrEmpty(IRun run, string key) {
         IItem param;
         if (run.Parameters.TryGetValue(key, out param)) {
           var bv = param as BoolValue;
-          return bv != null ? (bv.Value ? "MAX" : "MIN") : string.Empty;
-        }
-        return string.Empty;
+          if (bv != null) return bv.Value;
+        }
+        return null;
       }
 
@@ -1375,5 +1481,5 @@
           (DisplayProblemName ? ProblemName : string.Empty),
           (DisplayEvaluator ? Evaluator : string.Empty),
-          (DisplayMaximization ? Maximization : string.Empty),
+          (DisplayMaximization && Maximization.HasValue ? (Maximization.Value ? "MAX" : "MIN") : string.Empty),
           !double.IsNaN(BestKnownQuality) ? BestKnownQuality.ToString(CultureInfo.CurrentCulture.NumberFormat) : string.Empty }.Where(x => !string.IsNullOrEmpty(x)));
       }
@@ -1386,11 +1492,11 @@
     }
 
-    private class CostComparer : Comparer<Tuple<double, double>> {
-      public override int Compare(Tuple<double, double> x, Tuple<double, double> y) {
-        return x.Item1.CompareTo(y.Item1);
-      }
-    }
-
-    private class TargetComparer : Comparer<Tuple<double, double>> {
+    private class CostComparer : Comparer<ConvergenceGraphPoint> {
+      public override int Compare(ConvergenceGraphPoint x, ConvergenceGraphPoint y) {
+        return x.Runlength.CompareTo(y.Runlength);
+      }
+    }
+
+    private class TargetComparer : Comparer<ConvergenceGraphPoint> {
       public bool Maximization { get; private set; }
       public TargetComparer(bool maximization) {
@@ -1398,8 +1504,84 @@
       }
 
-      public override int Compare(Tuple<double, double> x, Tuple<double, double> y) {
-        return Maximization ? x.Item2.CompareTo(y.Item2) : y.Item2.CompareTo(x.Item2);
-      }
-    }
+      public override int Compare(ConvergenceGraphPoint x, ConvergenceGraphPoint y) {
+        return Maximization ? x.Quality.CompareTo(y.Quality) : y.Quality.CompareTo(x.Quality);
+      }
+    }
+
+    private class ConvergenceGraph : IEnumerable<ConvergenceGraphPoint> {
+      private List<ConvergenceGraphPoint> data;
+      private bool maximization;
+      private string xAxisLabel;
+
+      public string XAxisName { get { return xAxisLabel; } }
+
+      public int Points {
+        get { return data.Count; }
+      }
+
+      public double TotalRunlength {
+        get { return data.Last().Runlength; }
+      }
+
+      public double BestQuality {
+        get { return data.Last().Quality; }
+      }
+
+      public double QualityAt(double runlength) {
+        var point = data.SkipWhile(x => x.Runlength < runlength).FirstOrDefault();
+        if (point == null) return double.NaN;
+        return point.Quality;
+      }
+
+      public double RunlengthFor(double quality) {
+        var point = (maximization ? data.SkipWhile(x => x.Quality < quality) : data.SkipWhile(x => x.Quality > quality)).FirstOrDefault();
+        if (point == null) return double.NaN;
+        return point.Runlength;
+      }
+
+      public ConvergenceGraphPoint this[int point] {
+        get { return data[point]; }
+      }
+
+      public ConvergenceGraph(IndexedDataTable<double> table, bool maximization) {
+        data = table.Rows.First().Values.Select(x => new ConvergenceGraphPoint() { Runlength = x.Item1, Quality = x.Item2 }).ToList();
+        xAxisLabel = table.VisualProperties.XAxisTitle;
+        this.maximization = maximization;
+      }
+
+      public IEnumerator<ConvergenceGraphPoint> GetEnumerator() {
+        return data.GetEnumerator();
+      }
+
+      IEnumerator IEnumerable.GetEnumerator() {
+        return data.GetEnumerator();
+      }
+
+      public int BinarySearch(ConvergenceGraphPoint item, IComparer<ConvergenceGraphPoint> comparer) {
+        return data.BinarySearch(item, comparer);
+      }
+
+      public int BinarySearch(int index, int count, ConvergenceGraphPoint point, IComparer<ConvergenceGraphPoint> comparer) {
+        return data.BinarySearch(index, count, point, comparer);
+      }
+
+      public IEnumerable<Tuple<double, double>> ToTuples() {
+        return data.Select(x => Tuple.Create(x.Runlength, x.Quality));
+      }
+    }
+
+    private class ConvergenceGraphPoint {
+      public double Runlength { get; set; }
+      public double Quality { get; set; }
+
+      public ConvergenceGraphPoint() {
+
+      }
+      public ConvergenceGraphPoint(double runlength, double quality) {
+        Runlength = runlength;
+        Quality = quality;
+      }
+    }
+    #endregion
   }
 }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/BasicProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/BasicProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/BasicProblem.cs	(revision 16892)
@@ -23,8 +23,9 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -157,4 +158,19 @@
       OnOperatorsChanged();
     }
+
+    protected override IEnumerable<KeyValuePair<string, IItem>> GetCollectedValues(IValueParameter param) {
+      if (param.Value == null) yield break;
+      if (param.GetsCollected) {
+        if (param == EncodingParameter) // store only the name of the encoding
+          yield return new KeyValuePair<string, IItem>(String.Empty, new StringValue(EncodingParameter.Value.Name));
+        else yield return new KeyValuePair<string, IItem>(String.Empty, param.Value);
+      }
+      var parameterizedItem = param.Value as IParameterizedItem;
+      if (parameterizedItem != null) {
+        var children = new Dictionary<string, IItem>();
+        parameterizedItem.CollectParameterValues(children);
+        foreach (var child in children) yield return child;
+      }
+    }
   }
 }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Encoding.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Encoding.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Encoding.cs	(revision 16892)
@@ -23,8 +23,8 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -92,5 +92,7 @@
     protected Encoding(string name)
       : base(name) {
-      Parameters.Add(new FixedValueParameter<ReadOnlyItemSet<IOperator>>(name + ".Operators", "The operators that the encoding specifies.", encodingOperators.AsReadOnly()));
+      Parameters.Add(new FixedValueParameter<ReadOnlyItemSet<IOperator>>(name + ".Operators", "The operators that the encoding specifies.", encodingOperators.AsReadOnly()) {
+        GetsCollected = false
+      });
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/MultiObjectiveBasicProblem.cs	(revision 16892)
@@ -21,9 +21,9 @@
 
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -59,5 +59,4 @@
     
     protected override void OnOperatorsChanged() {
-      base.OnOperatorsChanged();
       if (Encoding != null) {
         PruneSingleObjectiveOperators(Encoding);
@@ -69,4 +68,5 @@
         }
       }
+      base.OnOperatorsChanged();
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCreator.cs	(revision 16892)
@@ -22,20 +22,36 @@
 using System;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
+using HeuristicLab.Parameters;
 
 namespace HeuristicLab.Optimization {
   [Item("MultiEncodingCreator", "Contains solution creators that together create a multi-encoding.")]
   [StorableType("E261B506-6F74-4BC4-8164-5ACE20FBC319")]
-  public sealed class MultiEncodingCreator : MultiEncodingOperator<ISolutionCreator>, ISolutionCreator {
+  public sealed class MultiEncodingCreator : MultiEncodingOperator<ISolutionCreator>, ISolutionCreator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override string OperatorPrefix => "Creator";
+
     [StorableConstructor]
     private MultiEncodingCreator(StorableConstructorFlag _) : base(_) { }
 
     private MultiEncodingCreator(MultiEncodingCreator original, Cloner cloner) : base(original, cloner) { }
-    public MultiEncodingCreator() { }
+    public MultiEncodingCreator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator used by the individual operators."));
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new MultiEncodingCreator(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Random")) {
+        Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator used by the individual operators."));
+      }
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCrossover.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCrossover.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingCrossover.cs	(revision 16892)
@@ -20,18 +20,34 @@
 #endregion
 
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
+using HeuristicLab.Parameters;
 
 namespace HeuristicLab.Optimization {
   [Item("MultiEncoding Crossover", "Applies different crossovers to cross a multi-encoding.")]
   [StorableType("BB0A04E2-899D-460C-82A2-5E4CEEDE8996")]
-  public sealed class MultiEncodingCrossover : MultiEncodingOperator<ICrossover>, ICrossover {
+  public sealed class MultiEncodingCrossover : MultiEncodingOperator<ICrossover>, ICrossover, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override string OperatorPrefix => "Crossover";
+
     [StorableConstructor]
     private MultiEncodingCrossover(StorableConstructorFlag _) : base(_) { }
     private MultiEncodingCrossover(MultiEncodingCrossover original, Cloner cloner) : base(original, cloner) { }
-    public MultiEncodingCrossover() { }
+    public MultiEncodingCrossover() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator used by the individual operators."));
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) { return new MultiEncodingCrossover(this, cloner); }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Random")) {
+        Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator used by the individual operators."));
+      }
+    }
   }
 }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingManipulator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingManipulator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingManipulator.cs	(revision 16892)
@@ -20,20 +20,36 @@
 #endregion
 
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
+using HeuristicLab.Parameters;
 
 namespace HeuristicLab.Optimization {
   [Item("MultiEncoding Manipulator", "Applies different manipulators to change a multi-encoding.")]
   [StorableType("574D0530-47E8-4FD9-8AC8-B8EA2DE3C203")]
-  public sealed class MultiEncodingManipulator : MultiEncodingOperator<IManipulator>, IManipulator {
+  public sealed class MultiEncodingManipulator : MultiEncodingOperator<IManipulator>, IManipulator, IStochasticOperator {
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
+    }
+
+    public override string OperatorPrefix => "Manipulator";
+
     [StorableConstructor]
     private MultiEncodingManipulator(StorableConstructorFlag _) : base(_) { }
     private MultiEncodingManipulator(MultiEncodingManipulator original, Cloner cloner)
       : base(original, cloner) { }
-    public MultiEncodingManipulator() { }
+    public MultiEncodingManipulator() {
+      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator used by the individual operators."));
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) { return new MultiEncodingManipulator(this, cloner); }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("Random")) {
+        Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator used by the individual operators."));
+      }
+    }
+
   }
 }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingOperator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingOperator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/Operators/MultiEncodingOperator.cs	(revision 16892)
@@ -23,9 +23,9 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -39,8 +39,8 @@
     }
 
+    public abstract string OperatorPrefix { get; }
+
     [StorableConstructor]
-    protected MultiEncodingOperator(StorableConstructorFlag _) : base(_) {
-    }
-
+    protected MultiEncodingOperator(StorableConstructorFlag _) : base(_) { }
     protected MultiEncodingOperator(MultiEncodingOperator<T> original, Cloner cloner)
       : base(original, cloner) {
@@ -49,26 +49,37 @@
         encoding.OperatorsChanged += Encoding_OperatorsChanged;
     }
-
     protected MultiEncodingOperator() : base() { }
 
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
-      foreach (var encoding in encodings)
+      foreach (var encoding in encodings) {
+        // BackwardsCompatibility3.3
+        #region Backwards compatible code, remove with 3.4
+        if (Parameters.ContainsKey(encoding.Name) && !Parameters.ContainsKey(OperatorPrefix + "." + encoding.Name)) {
+          var oldParam = (IConstrainedValueParameter<T>)Parameters[encoding.Name];
+          var selected = oldParam.Value;
+          Parameters.Remove(oldParam);
+          var newParam = new ConstrainedValueParameter<T>(OperatorPrefix + "." + encoding.Name, new ItemSet<T>(oldParam.ValidValues));
+          newParam.Value = selected;
+          Parameters.Add(newParam);
+          oldParam.ValidValues.Clear();
+        }
+        #endregion
         encoding.OperatorsChanged += Encoding_OperatorsChanged;
+      }
     }
 
-
     public override IOperation Apply() {
-      var operations = Parameters.Select(p => p.ActualValue).OfType<IOperator>().Select(op => ExecutionContext.CreateOperation(op));
+      var operations = Parameters.Select(p => p.ActualValue).OfType<IOperator>().Select(op => ExecutionContext.CreateChildOperation(op));
       return new OperationCollection(operations);
     }
 
     public virtual void AddEncoding(IEncoding encoding) {
-      if (Parameters.ContainsKey(encoding.Name)) throw new ArgumentException(string.Format("Encoding {0} was already added.", encoding.Name));
+      if (Parameters.ContainsKey(OperatorPrefix + "." + encoding.Name)) throw new ArgumentException(string.Format("Encoding {0} was already added.", encoding.Name));
 
       encodings.Add(encoding);
       encoding.OperatorsChanged += Encoding_OperatorsChanged;
 
-      var param = new ConstrainedValueParameter<T>(encoding.Name, new ItemSet<T>(encoding.Operators.OfType<T>()));
+      var param = new ConstrainedValueParameter<T>(OperatorPrefix + "." + encoding.Name, new ItemSet<T>(encoding.Operators.OfType<T>()));
       param.Value = param.ValidValues.First();
       Parameters.Add(param);
@@ -78,11 +89,11 @@
       if (!encodings.Remove(encoding)) throw new ArgumentException(string.Format("Encoding {0} was not added to the MultiEncoding.", encoding.Name));
       encoding.OperatorsChanged -= Encoding_OperatorsChanged;
-      return Parameters.Remove(encoding.Name);
+      return Parameters.Remove(OperatorPrefix + "." + encoding.Name);
     }
 
     protected IConstrainedValueParameter<T> GetParameter(IEncoding encoding) {
-      if (!Parameters.ContainsKey(encoding.Name)) throw new ArgumentException(string.Format("Encoding {0} was not added to the MultiEncoding.", encoding.Name));
+      if (!Parameters.ContainsKey(OperatorPrefix + "." + encoding.Name)) throw new ArgumentException(string.Format("Encoding {0} was not added to the MultiEncoding.", encoding.Name));
 
-      return (IConstrainedValueParameter<T>)Parameters[encoding.Name];
+      return (IConstrainedValueParameter<T>)Parameters[OperatorPrefix + "." + encoding.Name];
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/BasicProblems/SingleObjectiveBasicProblem.cs	(revision 16892)
@@ -23,9 +23,9 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -95,5 +95,4 @@
 
     protected override void OnOperatorsChanged() {
-      base.OnOperatorsChanged();
       if (Encoding != null) {
         PruneMultiObjectiveOperators(Encoding);
@@ -105,4 +104,5 @@
         }
       }
+      base.OnOperatorsChanged();
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs	(revision 16892)
@@ -112,5 +112,5 @@
     // BackwardsCompatibility3.3
     #region Backwards compatible code (remove with 3.4)
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "algorithm")]
     private IAlgorithm algorithm {
       set { optimizer = value; }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/Problems/Problem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/Problems/Problem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/Problems/Problem.cs	(revision 16892)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Drawing;
+using HEAL.Attic;
 using HeuristicLab.Collections;
 using HeuristicLab.Common;
@@ -28,5 +29,4 @@
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -52,5 +52,5 @@
     protected Problem()
       : base() {
-      Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(), false));
+      Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>()) { GetsCollected = false });
       OperatorsParameter.Hidden = true;
       RegisterEventHandlers();
@@ -66,5 +66,5 @@
         if (operators != null) {
           Parameters.Remove(OperatorsParameterName);
-          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(operators), false));
+          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(operators)) { GetsCollected = false });
           OperatorsParameter.Hidden = true;
         }
@@ -84,5 +84,5 @@
     // BackwardsCompatibility3.3
     #region Backwards compatible code, remove with 3.4
-    [Storable(Name = "Operators", AllowOneWay = true)]
+    [Storable(OldName = "Operators")]
     private IEnumerable<IOperator> StorableOperators {
       set {
@@ -95,5 +95,5 @@
         //necessary to convert old experiments files where no parameter was used for saving the operators
         if (!Parameters.ContainsKey(OperatorsParameterName)) {
-          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(), false));
+          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>()) { GetsCollected = false });
           OperatorsParameter.Hidden = true;
         }
@@ -107,5 +107,5 @@
         #region Backwards compatible code, remove with 3.4
         if (!Parameters.ContainsKey(OperatorsParameterName)) {
-          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>(), false));
+          Parameters.Add(new FixedValueParameter<ItemCollection<IItem>>(OperatorsParameterName, "The operators and items that the problem provides to the algorithms.", new ItemCollection<IItem>()) { GetsCollected = false });
           OperatorsParameter.Hidden = true;
         }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/Problems/UserDefinedProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/Problems/UserDefinedProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/Problems/UserDefinedProblem.cs	(revision 16892)
@@ -25,4 +25,5 @@
 using System.Linq;
 using System.Threading;
+using HEAL.Attic;
 using HeuristicLab.Collections;
 using HeuristicLab.Common;
@@ -30,5 +31,4 @@
 using HeuristicLab.Data;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.PluginInfrastructure;
 
@@ -130,5 +130,5 @@
         ItemList<IOperator> tmp = ((ValueParameter<ItemList<IOperator>>)Parameters["Operators"]).Value;
         Parameters.Remove("Operators");
-        Parameters.Add(new ValueParameter<ItemList<IItem>>("Operators", "The operators and items that the problem provides to the algorithms.", new ItemList<IItem>(tmp), false));
+        Parameters.Add(new ValueParameter<ItemList<IItem>>("Operators", "The operators and items that the problem provides to the algorithms.", new ItemList<IItem>(tmp)) { GetsCollected = false });
       }
       #endregion
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/RunCollection.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/RunCollection.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Optimization/3.3/RunCollection.cs	(revision 16892)
@@ -125,5 +125,5 @@
     // BackwardsCompatibility3.3
     #region Backwards compatible code, remove with 3.4
-    [Storable(AllowOneWay = true)]
+    [Storable(OldName = "AlgorithmName")]
     private string AlgorithmName {
       set { optimizerName = value; }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ConstrainedValueParameterView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ConstrainedValueParameterView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ConstrainedValueParameterView.cs	(revision 16892)
@@ -62,4 +62,5 @@
     protected override void DeregisterContentEvents() {
       Content.GetsCollectedChanged -= new EventHandler(Content_GetsCollectedChanged);
+      Content.ReadOnlyChanged -= new EventHandler(Content_ReadOnlyChanged);
       Content.ValidValues.ItemsAdded -= new CollectionItemsChangedEventHandler<T>(ValidValues_ItemsAdded);
       Content.ValidValues.ItemsRemoved -= new CollectionItemsChangedEventHandler<T>(ValidValues_ItemsRemoved);
@@ -76,4 +77,5 @@
       base.RegisterContentEvents();
       Content.GetsCollectedChanged += new EventHandler(Content_GetsCollectedChanged);
+      Content.ReadOnlyChanged += new EventHandler(Content_ReadOnlyChanged);
       Content.ValidValues.ItemsAdded += new CollectionItemsChangedEventHandler<T>(ValidValues_ItemsAdded);
       Content.ValidValues.ItemsRemoved += new CollectionItemsChangedEventHandler<T>(ValidValues_ItemsRemoved);
@@ -100,5 +102,5 @@
       base.SetEnabledStateOfControls();
       valueGroupBox.Enabled = Content != null;
-      valueComboBox.Enabled = (valueComboBox.Items.Count > 0) && !ReadOnly;
+      valueComboBox.Enabled = Content != null && valueComboBox.Items.Count > 0 && !Content.ReadOnly && !ReadOnly;
       showInRunCheckBox.Enabled = Content != null && !ReadOnly;
     }
@@ -153,4 +155,11 @@
         FillValueComboBox();
     }
+    protected virtual void Content_ReadOnlyChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_ReadOnlyChanged), sender, e);
+      else {
+        SetEnabledStateOfControls();
+      }
+    }
     protected virtual void Content_GetsCollectedChanged(object sender, EventArgs e) {
       if (InvokeRequired)
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ValueLookupParameterView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ValueLookupParameterView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ValueLookupParameterView.cs	(revision 16892)
@@ -74,4 +74,5 @@
       Content.ActualNameChanged -= new EventHandler(Content_ActualNameChanged);
       Content.GetsCollectedChanged -= new EventHandler(Content_GetsCollectedChanged);
+      Content.ReadOnlyChanged -= new EventHandler(Content_ReadOnlyChanged);
       Content.ValueChanged -= new EventHandler(Content_ValueChanged);
       base.DeregisterContentEvents();
@@ -86,4 +87,5 @@
       Content.ActualNameChanged += new EventHandler(Content_ActualNameChanged);
       Content.GetsCollectedChanged += new EventHandler(Content_GetsCollectedChanged);
+      Content.ReadOnlyChanged += new EventHandler(Content_ReadOnlyChanged);
       Content.ValueChanged += new EventHandler(Content_ValueChanged);
     }
@@ -108,6 +110,6 @@
       actualNameTextBox.Enabled = Content != null;
       actualNameTextBox.ReadOnly = ReadOnly;
-      setValueButton.Enabled = Content != null && !ReadOnly;
-      clearValueButton.Enabled = Content != null && Content.Value != null && !ReadOnly;
+      setValueButton.Enabled = Content != null && !Content.ReadOnly && !ReadOnly;
+      clearValueButton.Enabled = Content != null && !Content.ReadOnly && Content.Value != null && !ReadOnly;
       showInRunCheckBox.Enabled = Content != null && !ReadOnly;
     }
@@ -124,7 +126,14 @@
       else {
         SetDataTypeTextBoxText();
-        clearValueButton.Enabled = Content != null && Content.Value != null && !ReadOnly;
+        clearValueButton.Enabled = Content != null && !Content.ReadOnly && Content.Value != null && !ReadOnly;
         valueViewHost.ViewType = null;
         valueViewHost.Content = Content != null ? Content.Value : null;
+      }
+    }
+    protected virtual void Content_ReadOnlyChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_ReadOnlyChanged), sender, e);
+      else {
+        SetEnabledStateOfControls();
       }
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ValueParameterView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ValueParameterView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters.Views/3.3/ValueParameterView.cs	(revision 16892)
@@ -74,4 +74,5 @@
     protected override void DeregisterContentEvents() {
       Content.GetsCollectedChanged -= new EventHandler(Content_GetsCollectedChanged);
+      Content.ReadOnlyChanged -= new EventHandler(Content_ReadOnlyChanged);
       Content.ValueChanged -= new EventHandler(Content_ValueChanged);
       base.DeregisterContentEvents();
@@ -85,4 +86,5 @@
       base.RegisterContentEvents();
       Content.GetsCollectedChanged += new EventHandler(Content_GetsCollectedChanged);
+      Content.ReadOnlyChanged += new EventHandler(Content_ReadOnlyChanged);
       Content.ValueChanged += new EventHandler(Content_ValueChanged);
     }
@@ -103,6 +105,6 @@
     protected override void SetEnabledStateOfControls() {
       base.SetEnabledStateOfControls();
-      setValueButton.Enabled = Content != null && !(Content is IFixedValueParameter) && !ReadOnly;
-      clearValueButton.Enabled = Content != null && Content.Value != null && !(Content is IFixedValueParameter) && !(Content is ValueParameter<T>) && !ReadOnly;
+      setValueButton.Enabled = Content != null && !Content.ReadOnly && !(Content is IFixedValueParameter) && !ReadOnly;
+      clearValueButton.Enabled = Content != null && !Content.ReadOnly && Content.Value != null && !(Content is IFixedValueParameter) && !(Content is ValueParameter<T>) && !ReadOnly;
       showInRunCheckBox.Enabled = Content != null && !ReadOnly;
     }
@@ -113,8 +115,16 @@
       else {
         SetDataTypeTextBoxText();
-        setValueButton.Enabled = Content != null && !(Content is IFixedValueParameter) && !ReadOnly;
-        clearValueButton.Enabled = Content != null && Content.Value != null && !(Content is IFixedValueParameter<T>) && !(Content is ValueParameter<T>) && !ReadOnly;
+        setValueButton.Enabled = Content != null && !Content.ReadOnly && !(Content is IFixedValueParameter) && !ReadOnly;
+        clearValueButton.Enabled = Content != null && !Content.ReadOnly && Content.Value != null && !(Content is IFixedValueParameter<T>) && !(Content is ValueParameter<T>) && !ReadOnly;
         valueViewHost.ViewType = null;
         valueViewHost.Content = Content != null ? Content.Value : null;
+      }
+    }
+
+    protected virtual void Content_ReadOnlyChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_ReadOnlyChanged), sender, e);
+      else {
+        SetEnabledStateOfControls();
       }
     }
@@ -135,6 +145,5 @@
         try {
           Content.Value = (T)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
           ErrorHandling.ShowErrorDialog(this, ex);
         }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ConstrainedValueParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ConstrainedValueParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ConstrainedValueParameter.cs	(revision 16892)
@@ -22,8 +22,8 @@
 using System;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -47,15 +47,9 @@
     public ConstrainedValueParameter() : base() { }
     public ConstrainedValueParameter(string name) : base(name) { }
-    public ConstrainedValueParameter(string name, bool getsCollected) : base(name, getsCollected) { }
     public ConstrainedValueParameter(string name, ItemSet<T> validValues) : base(name, validValues) { }
-    public ConstrainedValueParameter(string name, ItemSet<T> validValues, bool getsCollected) : base(name, validValues, getsCollected) { }
     public ConstrainedValueParameter(string name, ItemSet<T> validValues, T value) : base(name, validValues, value) { }
-    public ConstrainedValueParameter(string name, ItemSet<T> validValues, T value, bool getsCollected) : base(name, validValues, value, getsCollected) { }
     public ConstrainedValueParameter(string name, string description) : base(name, description) { }
-    public ConstrainedValueParameter(string name, string description, bool getsCollected) : base(name, description, getsCollected) { }
     public ConstrainedValueParameter(string name, string description, ItemSet<T> validValues) : base(name, description, validValues) { }
-    public ConstrainedValueParameter(string name, string description, ItemSet<T> validValues, bool getsCollected) : base(name, description, validValues, getsCollected) { }
     public ConstrainedValueParameter(string name, string description, ItemSet<T> validValues, T value) : base(name, description, validValues, value) { }
-    public ConstrainedValueParameter(string name, string description, ItemSet<T> validValues, T value, bool getsCollected) : base(name, description, validValues, value, getsCollected) { }
 
     public override IDeepCloneable Clone(Cloner cloner) {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/FixedValueParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/FixedValueParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/FixedValueParameter.cs	(revision 16892)
@@ -21,7 +21,7 @@
 
 using System;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -31,5 +31,5 @@
   [Item("FixedValueParameter", "A parameter whose value is defined in the parameter itself and cannot be set.")]
   [StorableType("7787B99D-5F32-4639-B47A-76CB4D204392")]
-  public class FixedValueParameter<T> : ValueParameter<T>, IFixedValueParameter<T> where T : class,IItem, new() {
+  public class FixedValueParameter<T> : ValueParameter<T>, IFixedValueParameter<T> where T : class, IItem, new() {
 
     public override T Value {
@@ -46,11 +46,7 @@
     public FixedValueParameter() : base() { }
     public FixedValueParameter(string name) : base(name) { }
-    public FixedValueParameter(string name, bool getsCollected) : base(name, getsCollected) { }
     public FixedValueParameter(string name, T value) : base(name, value) { }
-    public FixedValueParameter(string name, T value, bool getsCollected) : base(name, value, getsCollected) { }
     public FixedValueParameter(string name, string description) : base(name, description) { }
-    public FixedValueParameter(string name, string description, bool getsCollected) : base(name, description, getsCollected) { }
     public FixedValueParameter(string name, string description, T value) : base(name, description, value) { }
-    public FixedValueParameter(string name, string description, T value, bool getsCollected) : base(name, description, value, getsCollected) { }
 
     public override IDeepCloneable Clone(Cloner cloner) {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OperatorParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OperatorParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OperatorParameter.cs	(revision 16892)
@@ -20,7 +20,7 @@
 #endregion
 
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -36,11 +36,7 @@
     public OperatorParameter() : base("Anonymous") { }
     public OperatorParameter(string name) : base(name) { }
-    public OperatorParameter(string name, bool getsCollected) : base(name, getsCollected) { }
     public OperatorParameter(string name, IOperator value) : base(name, value) { }
-    public OperatorParameter(string name, IOperator value, bool getsCollected) : base(name, value, getsCollected) { }
     public OperatorParameter(string name, string description) : base(name, description) { }
-    public OperatorParameter(string name, string description, bool getsCollected) : base(name, description, getsCollected) { }
     public OperatorParameter(string name, string description, IOperator value) : base(name, description, value) { }
-    public OperatorParameter(string name, string description, IOperator value, bool getsCollected) : base(name, description, value, getsCollected) { }
 
     public override IDeepCloneable Clone(Cloner cloner) {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OptionalConstrainedValueParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OptionalConstrainedValueParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OptionalConstrainedValueParameter.cs	(revision 16892)
@@ -22,8 +22,8 @@
 using System;
 using System.Drawing;
+using HEAL.Attic;
 using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -40,5 +40,5 @@
       }
     }
-      
+
     [Storable]
     private ItemSet<T> validValues;
@@ -52,4 +52,5 @@
       get { return this.value; }
       set {
+        if (ReadOnly) throw new InvalidOperationException("Cannot set the value of a readonly parameter.");
         if (value != this.value) {
           if ((value != null) && !validValues.Contains(value)) throw new ArgumentException("Invalid value.");
@@ -74,4 +75,15 @@
     }
 
+    [Storable(DefaultValue = false)]
+    private bool readOnly;
+    public bool ReadOnly {
+      get { return readOnly; }
+      set {
+        if (value == readOnly) return;
+        readOnly = value;
+        OnReadOnlyChanged();
+      }
+    }
+
     [Storable(DefaultValue = true)]
     private bool getsCollected;
@@ -93,4 +105,5 @@
       validValues = cloner.Clone(original.validValues);
       value = cloner.Clone(original.value);
+      readOnly = original.readOnly;
       getsCollected = original.getsCollected;
       Initialize();
@@ -99,4 +112,5 @@
       : base("Anonymous", typeof(T)) {
       this.validValues = new ItemSet<T>();
+      this.readOnly = false;
       this.getsCollected = true;
       Initialize();
@@ -105,11 +119,6 @@
       : base(name, typeof(T)) {
       this.validValues = new ItemSet<T>();
-      this.getsCollected = true;
-      Initialize();
-    }
-    public OptionalConstrainedValueParameter(string name, bool getsCollected)
-      : base(name, typeof(T)) {
-      this.validValues = new ItemSet<T>();
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       Initialize();
     }
@@ -117,11 +126,6 @@
       : base(name, typeof(T)) {
       this.validValues = validValues;
-      this.getsCollected = true;
-      Initialize();
-    }
-    public OptionalConstrainedValueParameter(string name, ItemSet<T> validValues, bool getsCollected)
-      : base(name, typeof(T)) {
-      this.validValues = validValues;
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       Initialize();
     }
@@ -130,12 +134,6 @@
       this.validValues = validValues;
       this.value = value;
-      this.getsCollected = true;
-      Initialize();
-    }
-    public OptionalConstrainedValueParameter(string name, ItemSet<T> validValues, T value, bool getsCollected)
-      : base(name, typeof(T)) {
-      this.validValues = validValues;
-      this.value = value;
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       Initialize();
     }
@@ -143,11 +141,6 @@
       : base(name, description, typeof(T)) {
       this.validValues = new ItemSet<T>();
-      this.getsCollected = true;
-      Initialize();
-    }
-    public OptionalConstrainedValueParameter(string name, string description, bool getsCollected)
-      : base(name, description, typeof(T)) {
-      this.validValues = new ItemSet<T>();
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       Initialize();
     }
@@ -155,11 +148,6 @@
       : base(name, description, typeof(T)) {
       this.validValues = validValues;
-      this.getsCollected = true;
-      Initialize();
-    }
-    public OptionalConstrainedValueParameter(string name, string description, ItemSet<T> validValues, bool getsCollected)
-      : base(name, description, typeof(T)) {
-      this.validValues = validValues;
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       Initialize();
     }
@@ -168,12 +156,6 @@
       this.validValues = validValues;
       this.value = value;
-      this.getsCollected = true;
-      Initialize();
-    }
-    public OptionalConstrainedValueParameter(string name, string description, ItemSet<T> validValues, T value, bool getsCollected)
-      : base(name, description, typeof(T)) {
-      this.validValues = validValues;
-      this.value = value;
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       Initialize();
     }
@@ -212,4 +194,9 @@
       OnToStringChanged();
     }
+    public event EventHandler ReadOnlyChanged;
+    protected virtual void OnReadOnlyChanged() {
+      EventHandler handler = ReadOnlyChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
     public event EventHandler GetsCollectedChanged;
     protected virtual void OnGetsCollectedChanged() {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OptionalValueParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OptionalValueParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/OptionalValueParameter.cs	(revision 16892)
@@ -22,7 +22,7 @@
 using System;
 using System.Drawing;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -45,4 +45,5 @@
       get { return this.value; }
       set {
+        if (ReadOnly) throw new InvalidOperationException("Cannot set the value of a readonly parameter.");
         if (value != this.value) {
           DeregisterValueEvents();
@@ -63,4 +64,15 @@
           );
         Value = val;
+      }
+    }
+
+    [Storable(DefaultValue = false)]
+    private bool readOnly;
+    public bool ReadOnly {
+      get { return readOnly; }
+      set {
+        if (value == readOnly) return;
+        readOnly = value;
+        OnReadOnlyChanged();
       }
     }
@@ -108,4 +120,5 @@
       : base(original, cloner) {
       value = cloner.Clone(original.value);
+      readOnly = original.readOnly;
       getsCollected = original.getsCollected;
       reactOnValueToStringChangedAndValueItemImageChanged = original.reactOnValueToStringChangedAndValueItemImageChanged;
@@ -114,4 +127,5 @@
     public OptionalValueParameter()
       : base("Anonymous", typeof(T)) {
+      this.readOnly = false;
       this.getsCollected = true;
       this.reactOnValueToStringChangedAndValueItemImageChanged = true;
@@ -119,10 +133,6 @@
     public OptionalValueParameter(string name)
       : base(name, typeof(T)) {
-      this.getsCollected = true;
-      this.reactOnValueToStringChangedAndValueItemImageChanged = true;
-    }
-    public OptionalValueParameter(string name, bool getsCollected)
-      : base(name, typeof(T)) {
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       this.reactOnValueToStringChangedAndValueItemImageChanged = true;
     }
@@ -130,12 +140,6 @@
       : base(name, typeof(T)) {
       this.value = value;
-      this.getsCollected = true;
-      this.reactOnValueToStringChangedAndValueItemImageChanged = true;
-      RegisterValueEvents();
-    }
-    public OptionalValueParameter(string name, T value, bool getsCollected)
-      : base(name, typeof(T)) {
-      this.value = value;
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       this.reactOnValueToStringChangedAndValueItemImageChanged = true;
       RegisterValueEvents();
@@ -143,23 +147,14 @@
     public OptionalValueParameter(string name, string description)
       : base(name, description, typeof(T)) {
-      this.getsCollected = true;
-      this.reactOnValueToStringChangedAndValueItemImageChanged = true;
-    }
-    public OptionalValueParameter(string name, string description, bool getsCollected)
-      : base(name, description, typeof(T)) {
-      this.getsCollected = getsCollected;
-      this.reactOnValueToStringChangedAndValueItemImageChanged = true;
-    }
+      this.readOnly = false;
+      this.getsCollected = true;
+      this.reactOnValueToStringChangedAndValueItemImageChanged = true;
+    }
+
     public OptionalValueParameter(string name, string description, T value)
       : base(name, description, typeof(T)) {
       this.value = value;
-      this.getsCollected = true;
-      this.reactOnValueToStringChangedAndValueItemImageChanged = true;
-      RegisterValueEvents();
-    }
-    public OptionalValueParameter(string name, string description, T value, bool getsCollected)
-      : base(name, description, typeof(T)) {
-      this.value = value;
-      this.getsCollected = getsCollected;
+      this.readOnly = false;
+      this.getsCollected = true;
       this.reactOnValueToStringChangedAndValueItemImageChanged = true;
       RegisterValueEvents();
@@ -197,4 +192,10 @@
       OnToStringChanged();
     }
+
+    public event EventHandler ReadOnlyChanged;
+    protected virtual void OnReadOnlyChanged() {
+      EventHandler handler = ReadOnlyChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
     public event EventHandler GetsCollectedChanged;
     protected virtual void OnGetsCollectedChanged() {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ValueLookupParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ValueLookupParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ValueLookupParameter.cs	(revision 16892)
@@ -22,7 +22,7 @@
 using System;
 using System.Drawing;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -45,4 +45,5 @@
       get { return this.value; }
       set {
+        if (ReadOnly) throw new InvalidOperationException("Cannot set the value of a readonly parameter.");
         if (value != this.value) {
           DeregisterValueEvents();
@@ -66,4 +67,15 @@
     }
 
+    [Storable(DefaultValue = false)]
+    private bool readOnly;
+    public bool ReadOnly {
+      get { return readOnly; }
+      set {
+        if (value == readOnly) return;
+        readOnly = value;
+        OnReadOnlyChanged();
+      }
+    }
+
     [Storable(DefaultValue = true)]
     private bool getsCollected;
@@ -84,4 +96,5 @@
       : base(original, cloner) {
       value = cloner.Clone(original.value);
+      readOnly = original.readOnly;
       getsCollected = original.getsCollected;
       RegisterValueEvents();
@@ -89,4 +102,5 @@
     public ValueLookupParameter()
       : base() {
+      this.readOnly = false;
       this.Hidden = false;
       this.getsCollected = true;
@@ -94,59 +108,35 @@
     public ValueLookupParameter(string name)
       : base(name) {
+      this.readOnly = false;
       this.Hidden = false;
       this.getsCollected = true;
-    }
-    public ValueLookupParameter(string name, bool getsCollected)
-      : base(name) {
-      this.Hidden = false;
-      this.getsCollected = getsCollected;
     }
     public ValueLookupParameter(string name, T value)
       : base(name) {
       this.value = value;
+      this.readOnly = false;
       this.Hidden = false;
       this.getsCollected = true;
       RegisterValueEvents();
     }
-    public ValueLookupParameter(string name, T value, bool getsCollected)
-      : base(name) {
-      this.value = value;
-      this.Hidden = false;
-      this.getsCollected = getsCollected;
-      RegisterValueEvents();
-    }
     public ValueLookupParameter(string name, string description)
       : base(name, description) {
+      this.readOnly = false;
       this.Hidden = false;
       this.getsCollected = true;
-    }
-    public ValueLookupParameter(string name, string description, bool getsCollected)
-      : base(name, description) {
-      this.Hidden = false;
-      this.getsCollected = getsCollected;
     }
     public ValueLookupParameter(string name, string description, T value)
       : base(name, description) {
       this.value = value;
+      this.readOnly = false;
       this.Hidden = false;
       this.getsCollected = true;
       RegisterValueEvents();
     }
-    public ValueLookupParameter(string name, string description, T value, bool getsCollected)
-      : base(name, description) {
-      this.value = value;
-      this.Hidden = false;
-      this.getsCollected = getsCollected;
-      RegisterValueEvents();
-    }
     public ValueLookupParameter(string name, string description, string actualName)
       : base(name, description, actualName) {
+      this.readOnly = false;
       this.Hidden = false;
       this.getsCollected = true;
-    }
-    public ValueLookupParameter(string name, string description, string actualName, bool getsCollected)
-      : base(name, description, actualName) {
-      this.Hidden = false;
-      this.getsCollected = getsCollected;
     }
     #endregion
@@ -177,4 +167,9 @@
       OnToStringChanged();
     }
+    public event EventHandler ReadOnlyChanged;
+    protected virtual void OnReadOnlyChanged() {
+      EventHandler handler = ReadOnlyChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
     public event EventHandler GetsCollectedChanged;
     protected virtual void OnGetsCollectedChanged() {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ValueParameter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ValueParameter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Parameters/3.3/ValueParameter.cs	(revision 16892)
@@ -22,7 +22,7 @@
 using System;
 using System.Reflection;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Parameters {
@@ -47,12 +47,8 @@
     public ValueParameter() : base() { }
     public ValueParameter(string name) : base(name) { base.Value = CreateDefaultValue(); }
-    public ValueParameter(string name, bool getsCollected) : base(name, getsCollected) { base.Value = CreateDefaultValue(); }
     public ValueParameter(string name, T value) : base(name, value) { }
-    public ValueParameter(string name, T value, bool getsCollected) : base(name, value, getsCollected) { }
     public ValueParameter(string name, string description) : base(name, description) { base.Value = CreateDefaultValue(); }
-    public ValueParameter(string name, string description, bool getsCollected) : base(name, description, getsCollected) { base.Value = CreateDefaultValue(); }
     public ValueParameter(string name, string description, T value) : base(name, description, value) { }
-    public ValueParameter(string name, string description, T value, bool getsCollected) : base(name, description, value, getsCollected) { }
-                                                                                  
+
     protected T CreateDefaultValue() {
       Type type = typeof(T);
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableMemberInfo.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableMemberInfo.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableMemberInfo.cs	(revision 16892)
@@ -41,8 +41,8 @@
     }
     public StorableMemberInfo(StorableAttribute attribute, MemberInfo memberInfo) {
-      DisentangledName = attribute.Name;
+      DisentangledName = string.IsNullOrEmpty(attribute.OldName) ? attribute.Name : attribute.OldName;
       DefaultValue = attribute.DefaultValue;
       MemberInfo = memberInfo;
-      if (!attribute.AllowOneWay)
+      if (string.IsNullOrEmpty(attribute.OldName) && !attribute.AllowOneWay)
         CheckPropertyAccess(memberInfo as PropertyInfo);
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj	(revision 16892)
@@ -126,4 +126,6 @@
     <Compile Include="ModelCreators\NormalDistributedThresholdsModelCreator.cs" />
     <Compile Include="MultiObjective\SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs" />
+    <Compile Include="SingleObjective\SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator.cs" />
+    <Compile Include="SingleObjective\SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator.cs" />
     <Compile Include="SymbolicClassificationPhenotypicDiversityAnalyzer.cs" />
     <Compile Include="SymbolicClassificationPruningAnalyzer.cs" />
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator.cs	(revision 16892)
@@ -0,0 +1,158 @@
+﻿#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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  [NonDiscoverableType]
+  [Item("Weighted Performance Measures Evaluator", "Calculates the quality of a symbolic classification solution based on three weighted measures(normalized mean squared error, false negative rate(1-sensitivity) and false positve rate(1-specificity)).")]
+  [StorableType("0772F316-5E12-4153-857E-8625069B4677")]
+  public class SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator : SymbolicClassificationSingleObjectiveEvaluator {
+    private const string NormalizedMeanSquaredErrorWeightingFactorParameterName = "NormalizedMeanSquaredErrorWeightingFactor";
+    private const string FalseNegativeRateWeightingFactorParameterName = "FalseNegativeRateWeightingFactor";
+    private const string FalsePositiveRateWeightingFactorParameterName = "FalsePositiveRateWeightingFactor";
+    private const string ModelCreatorParameterName = "ModelCreator";
+
+    public override bool Maximization { get { return false; } }
+
+    #region parameter properties
+    public IFixedValueParameter<DoubleValue> NormalizedMeanSquaredErrorWeightingFactorParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[NormalizedMeanSquaredErrorWeightingFactorParameterName]; }
+    }
+    public IFixedValueParameter<DoubleValue> FalseNegativeRateWeightingFactorParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[FalseNegativeRateWeightingFactorParameterName]; }
+    }
+    public IFixedValueParameter<DoubleValue> FalsePositiveRateWeightingFactorParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[FalsePositiveRateWeightingFactorParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
+      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
+    }
+    #endregion
+
+    public double NormalizedMeanSquaredErrorWeightingFactor {
+      get { return NormalizedMeanSquaredErrorWeightingFactorParameter.Value.Value; }
+    }
+    public double FalseNegativeRateWeightingFactor {
+      get { return FalseNegativeRateWeightingFactorParameter.Value.Value; }
+    }
+    public double FalsePositiveRateWeightingFactor {
+      get { return FalsePositiveRateWeightingFactorParameter.Value.Value; }
+    }
+
+    [StorableConstructor]
+    protected SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator(StorableConstructorFlag _) : base(_) { }
+    protected SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator(SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator(this, cloner);
+    }
+
+    public SymbolicClassificationSingleObjectiveWeightedPerformanceMeasuresEvaluator()
+      : base() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(NormalizedMeanSquaredErrorWeightingFactorParameterName, "The weighting factor of the normalized mean squared error.", new DoubleValue(1)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(FalseNegativeRateWeightingFactorParameterName, "The weighting factor of the false negative rate (1-sensitivity).", new DoubleValue(1)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(FalsePositiveRateWeightingFactorParameterName, "The weighting factor of the false positive rate (1-specificity).", new DoubleValue(1)));
+      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "The model creator which is used during the evaluations."));
+    }
+
+    public override IOperation InstrumentedApply() {
+      IEnumerable<int> rows = GenerateRowsToEvaluate();
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
+      var creator = ModelCreatorParameter.ActualValue;
+      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
+      var estimationLimits = EstimationLimitsParameter.ActualValue;
+      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
+
+
+      double quality = Calculate(interpreter, tree, estimationLimits.Lower, estimationLimits.Upper,
+              ProblemDataParameter.ActualValue, rows, applyLinearScaling, creator, NormalizedMeanSquaredErrorWeightingFactor, FalseNegativeRateWeightingFactor, FalsePositiveRateWeightingFactor);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+      return base.InstrumentedApply();
+    }
+
+    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IClassificationProblemData problemData,
+                IEnumerable<int> rows, bool applyLinearScaling, ISymbolicClassificationModelCreator modelCreator, double normalizedMeanSquaredErrorWeightingFactor, double falseNegativeRateWeightingFactor, double falsePositiveRateWeightingFactor) {
+      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
+      var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit).ToArray();
+      OnlineCalculatorError errorState;
+      double nmse;
+
+      //calculate performance measures
+      string positiveClassName = problemData.PositiveClass;
+      double[] classValues, thresholds;
+      IEnumerable<double> estimatedClassValues = null;
+      ISymbolicDiscriminantFunctionClassificationModel m;
+
+      var model = modelCreator.CreateSymbolicClassificationModel(problemData.TargetVariable, tree, interpreter, lowerEstimationLimit, upperEstimationLimit);
+      if ((m = model as ISymbolicDiscriminantFunctionClassificationModel) != null) {
+        m.ThresholdCalculator.Calculate(problemData, boundedEstimatedValues, targetClassValues, out classValues, out thresholds);
+        m.SetThresholdsAndClassValues(thresholds, classValues);
+        estimatedClassValues = m.GetEstimatedClassValues(boundedEstimatedValues);
+      } else {
+        model.RecalculateModelParameters(problemData, rows);
+        estimatedClassValues = model.GetEstimatedClassValues(problemData.Dataset, rows);
+      }
+
+      var performanceCalculator = new ClassificationPerformanceMeasuresCalculator(positiveClassName, problemData.GetClassValue(positiveClassName));
+      performanceCalculator.Calculate(targetClassValues, estimatedClassValues);
+      if (performanceCalculator.ErrorState != OnlineCalculatorError.None)
+        return Double.NaN;
+      double falseNegativeRate = 1 - performanceCalculator.TruePositiveRate;
+      double falsePositiveRate = performanceCalculator.FalsePositiveRate;
+
+      if (applyLinearScaling) {
+        throw new NotSupportedException("The Weighted Performance Measures Evaluator does not suppport linear scaling!");
+      }
+      nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetClassValues, boundedEstimatedValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) return Double.NaN;
+      return normalizedMeanSquaredErrorWeightingFactor * nmse + falseNegativeRateWeightingFactor * falseNegativeRate + falsePositiveRateWeightingFactor * falsePositiveRate;
+    }
+
+    public override double Evaluate(IExecutionContext context, ISymbolicExpressionTree tree, IClassificationProblemData problemData, IEnumerable<int> rows) {
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
+      EstimationLimitsParameter.ExecutionContext = context;
+      ApplyLinearScalingParameter.ExecutionContext = context;
+      ModelCreatorParameter.ExecutionContext = context;
+
+      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
+                                      problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, ModelCreatorParameter.ActualValue, NormalizedMeanSquaredErrorWeightingFactorParameter.Value.Value, FalseNegativeRateWeightingFactor, FalsePositiveRateWeightingFactor);
+
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
+      EstimationLimitsParameter.ExecutionContext = null;
+      ApplyLinearScalingParameter.ExecutionContext = null;
+      ModelCreatorParameter.ExecutionContext = null;
+
+      return quality;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator.cs	(revision 16892)
@@ -0,0 +1,141 @@
+﻿#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 HEAL.Attic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
+  [NonDiscoverableType]
+  [Item("Weighted Residuals Mean Squared Error Evaluator", @"A modified mean squared error evaluator that enables the possibility to weight residuals differently.
+The first residual category belongs to estimated values which definitely belong to a specific class because the estimated value is located above the maximum or below the minimum of all the class values (DefiniteResidualsWeight).
+The second residual category represents residuals which belong to the positive class whereby the estimated value is located between the positive and a negative class (PositiveClassResidualsWeight).
+All other cases are represented by the third category (NegativeClassesResidualsWeight).
+The weight gets multiplied to the squared error. Note that the Evaluator acts like a normal MSE-Evaluator if all the weights are set to 1.")]
+  [StorableType("A3193296-1A0F-46E2-8F43-22E2ED9CFFC5")]
+  public sealed class SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator : SymbolicClassificationSingleObjectiveEvaluator {
+    private const string DefiniteResidualsWeightParameterName = "DefiniteResidualsWeight";
+    private const string PositiveClassResidualsWeightParameterName = "PositiveClassResidualsWeight";
+    private const string NegativeClassesResidualsWeightParameterName = "NegativeClassesResidualsWeight";
+    [StorableConstructor]
+    private SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator(StorableConstructorFlag _) : base(_) { }
+    private SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator(SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator(this, cloner);
+    }
+
+    public SymbolicClassificationSingleObjectiveWeightedResidualsMeanSquaredErrorEvaluator()
+      : base() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(DefiniteResidualsWeightParameterName, "Weight of residuals which definitely belong to a specific class because the estimated values is located above the maximum or below the minimum of all the class values.", new DoubleValue(1)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(PositiveClassResidualsWeightParameterName, "Weight of residuals which belong to the positive class whereby the estimated value is located between the positive and a negative class.", new DoubleValue(1)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(NegativeClassesResidualsWeightParameterName, "Weight of residuals which are not covered by the DefiniteResidualsWeight or the PositiveClassResidualsWeight.", new DoubleValue(1)));
+    }
+
+    #region parameter properties
+    public IFixedValueParameter<DoubleValue> DefiniteResidualsWeightParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[DefiniteResidualsWeightParameterName]; }
+    }
+    public IFixedValueParameter<DoubleValue> PositiveClassResidualsWeightParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[PositiveClassResidualsWeightParameterName]; }
+    }
+    public IFixedValueParameter<DoubleValue> NegativeClassesResidualsWeightParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[NegativeClassesResidualsWeightParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public override bool Maximization { get { return false; } }
+
+    public double DefiniteResidualsWeight {
+      get { return DefiniteResidualsWeightParameter.Value.Value; }
+    }
+    public double PositiveClassResidualsWeight {
+      get { return PositiveClassResidualsWeightParameter.Value.Value; }
+    }
+    public double NegativeClassesResidualsWeight {
+      get { return NegativeClassesResidualsWeightParameter.Value.Value; }
+    }
+    #endregion
+
+    public override IOperation InstrumentedApply() {
+      IEnumerable<int> rows = GenerateRowsToEvaluate();
+      var solution = SymbolicExpressionTreeParameter.ActualValue;
+      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, ProblemDataParameter.ActualValue, rows, ApplyLinearScalingParameter.ActualValue.Value,
+        DefiniteResidualsWeight, PositiveClassResidualsWeight, NegativeClassesResidualsWeight);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+      return base.InstrumentedApply();
+    }
+
+    public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IClassificationProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling,
+      double definiteResidualsWeight, double positiveClassResidualsWeight, double negativeClassesResidualsWeight) {
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
+      IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
+      OnlineCalculatorError errorState;
+
+      double positiveClassValue = problemData.GetClassValue(problemData.PositiveClass);
+      //get class values min/max
+      double classValuesMin = problemData.ClassValues.ElementAtOrDefault(0);
+      double classValuesMax = classValuesMin;
+      foreach (double classValue in problemData.ClassValues) {
+        if (classValuesMin > classValue) classValuesMin = classValue;
+        if (classValuesMax < classValue) classValuesMax = classValue;
+      }
+
+      double quality;
+      if (applyLinearScaling) {
+        var calculator = new OnlineWeightedClassificationMeanSquaredErrorCalculator(positiveClassValue, classValuesMax, classValuesMin,
+          definiteResidualsWeight, positiveClassResidualsWeight, negativeClassesResidualsWeight);
+        CalculateWithScaling(targetValues, estimatedValues, lowerEstimationLimit, upperEstimationLimit, calculator, problemData.Dataset.Rows);
+        errorState = calculator.ErrorState;
+        quality = calculator.WeightedResidualsMeanSquaredError;
+      } else {
+        IEnumerable<double> boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
+        quality = OnlineWeightedClassificationMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, positiveClassValue, classValuesMax,
+          classValuesMin, definiteResidualsWeight, positiveClassResidualsWeight, negativeClassesResidualsWeight, out errorState);
+      }
+      if (errorState != OnlineCalculatorError.None) return Double.NaN;
+      return quality;
+    }
+
+    public override double Evaluate(IExecutionContext context, ISymbolicExpressionTree tree, IClassificationProblemData problemData, IEnumerable<int> rows) {
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
+      EstimationLimitsParameter.ExecutionContext = context;
+      ApplyLinearScalingParameter.ExecutionContext = context;
+
+      double quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, DefiniteResidualsWeight, PositiveClassResidualsWeight, NegativeClassesResidualsWeight);
+
+      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
+      EstimationLimitsParameter.ExecutionContext = null;
+      ApplyLinearScalingParameter.ExecutionContext = null;
+
+      return quality;
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs	(revision 16892)
@@ -81,5 +81,5 @@
       var classificationProblemData = problemData as IClassificationProblemData;
       if (classificationProblemData == null)
-        throw new ArgumentException("The problem data is not a regression problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+        throw new ArgumentException("The problem data is not compatible with this classification model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
       return IsProblemDataCompatible(classificationProblemData, out errorMessage);
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs	(revision 16892)
@@ -112,6 +112,10 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
+      var estimatedValues = GetEstimatedValues(dataset, rows);
+      return GetEstimatedClassValues(estimatedValues);
+    }
+    public IEnumerable<double> GetEstimatedClassValues(IEnumerable<double> estimatedValues) {
       if (!Thresholds.Any() && !ClassValues.Any()) throw new ArgumentException("No thresholds and class values were set for the current symbolic classification model.");
-      foreach (var x in GetEstimatedValues(dataset, rows)) {
+      foreach (var x in estimatedValues) {
         int classIndex = 0;
         // find first threshold value which is larger than x => class index = threshold index + 1
@@ -123,5 +127,4 @@
       }
     }
-
 
     public override ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs	(revision 16892)
@@ -46,12 +46,24 @@
     protected override ISymbolicExpressionTree OptimizeConstants(ISymbolicExpressionTree tree, IProgress progress) {
       const int constOptIterations = 50;
+      const int maxRepetitions = 1000;
       var regressionProblemData = Content.ProblemData;
       var model = Content.Model;
-      SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(model.Interpreter, tree, regressionProblemData, regressionProblemData.TrainingIndices,
-        applyLinearScaling: true, maxIterations: constOptIterations, updateVariableWeights: true, lowerEstimationLimit: model.LowerEstimationLimit, upperEstimationLimit: model.UpperEstimationLimit,
-        iterationCallback: (args, func, obj) => {
-          double newProgressValue = progress.ProgressValue + 1.0 / (constOptIterations + 2); // (maxIterations + 2) iterations are reported
-          progress.ProgressValue = Math.Min(newProgressValue, 1.0);
-        });
+      progress.CanBeStopped = true;
+      var prevResult = 0.0;
+      var result = 0.0;
+      int reps = 0;
+
+      do {
+        prevResult = result;
+        result = SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(model.Interpreter, tree, regressionProblemData, regressionProblemData.TrainingIndices,
+          applyLinearScaling: true, maxIterations: constOptIterations, updateVariableWeights: true, lowerEstimationLimit: model.LowerEstimationLimit, upperEstimationLimit: model.UpperEstimationLimit,
+          iterationCallback: (args, func, obj) => {
+            double newProgressValue = progress.ProgressValue + 1.0 / (constOptIterations + 2); // (maxIterations + 2) iterations are reported
+            progress.ProgressValue = Math.Min(newProgressValue, 1.0);
+          });
+        reps++;
+      } while (prevResult < result && reps < maxRepetitions &&
+               progress.ProgressState != ProgressState.StopRequested &&
+               progress.ProgressState != ProgressState.CancelRequested);
       return tree;
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 16892)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +30,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
@@ -114,8 +114,8 @@
     public SymbolicRegressionConstantOptimizationEvaluator()
       : base() {
-      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName, "Determines how many iterations should be calculated while optimizing the constant of a symbolic expression tree (0 indicates other or default stopping criterion).", new IntValue(10), true));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(ConstantOptimizationImprovementParameterName, "Determines the relative improvement which must be achieved in the constant optimization to continue with it (0 indicates other or default stopping criterion).", new DoubleValue(0), true) { Hidden = true });
-      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationProbabilityParameterName, "Determines the probability that the constants are optimized", new PercentValue(1), true));
-      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationRowsPercentageParameterName, "Determines the percentage of the rows which should be used for constant optimization", new PercentValue(1), true));
+      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName, "Determines how many iterations should be calculated while optimizing the constant of a symbolic expression tree (0 indicates other or default stopping criterion).", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(ConstantOptimizationImprovementParameterName, "Determines the relative improvement which must be achieved in the constant optimization to continue with it (0 indicates other or default stopping criterion).", new DoubleValue(0)) { Hidden = true });
+      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationProbabilityParameterName, "Determines the probability that the constants are optimized", new PercentValue(1)));
+      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationRowsPercentageParameterName, "Determines the percentage of the rows which should be used for constant optimization", new PercentValue(1)));
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateConstantsInTreeParameterName, "Determines if the constants in the tree should be overwritten by the optimized constants.", new BoolValue(true)) { Hidden = true });
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateVariableWeightsParameterName, "Determines if the variable weights in the tree should be  optimized.", new BoolValue(true)) { Hidden = true });
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs	(revision 16892)
@@ -90,5 +90,5 @@
       var regressionProblemData = problemData as IRegressionProblemData;
       if (regressionProblemData == null)
-        throw new ArgumentException("The problem data is not a regression problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+        throw new ArgumentException("The problem data is not compatible with this symbolic regression model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
       return IsProblemDataCompatible(regressionProblemData, out errorMessage);
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 16892)
@@ -83,15 +83,15 @@
         if (branch.SubtreeCount >= 2) {
           var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone();
-          var g = (ISymbolicExpressionTreeNode)branch.GetSubtree(1).Clone();
           var fprime = Derive(f, variableName);
-          var gprime = Derive(g, variableName);
-          var fgPrime = Sum(Product(f, gprime), Product(fprime, g));
-          for (int i = 2; i < branch.SubtreeCount; i++) {
+          for (int i = 1; i < branch.SubtreeCount; i++) {
+            var g = (ISymbolicExpressionTreeNode)branch.GetSubtree(i).Clone();
             var fg = Product((ISymbolicExpressionTreeNode)f.Clone(), (ISymbolicExpressionTreeNode)g.Clone());
-            var h = (ISymbolicExpressionTreeNode)branch.GetSubtree(i).Clone();
-            var hPrime = Derive(h, variableName);
-            fgPrime = Sum(Product(fgPrime, h), Product(fg, hPrime));
+            var gPrime = Derive(g, variableName);
+            var fgPrime = Sum(Product(fprime, g), Product(gPrime, f));
+            // prepare for next iteration
+            f = fg;
+            fprime = fgPrime;
           }
-          return fgPrime;
+          return fprime;
         } else
           // multiplication with only one argument has no effect -> derive the argument
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs	(revision 16892)
@@ -38,27 +38,34 @@
       double @const = 0) {
 
-      if (factorCoefficients.Length == 0 && coefficients.Length == 0) throw new ArgumentException();
+      if (factorCoefficients.Length == 0 && coefficients.Length == 0 && @const==0) throw new ArgumentException();
+
+      // Combine both trees
+      ISymbolicExpressionTreeNode add = (new Addition()).CreateTreeNode();
 
       // Create tree for double variables
-      ISymbolicExpressionTree tree = null;      
       if (coefficients.Length > 0) {
-        tree = CreateTree(variableNames, new int[variableNames.Length], coefficients, @const);
-        if (factorCoefficients.Length == 0) return tree;
+        var varTree = CreateTree(variableNames, new int[variableNames.Length], coefficients);
+        foreach (var varNode in varTree.IterateNodesPrefix().OfType<VariableTreeNode>())
+          add.AddSubtree(varNode);
       }
 
       // Create tree for string variables
-      ISymbolicExpressionTree factorTree = null;      
       if (factorCoefficients.Length > 0) {
-        factorTree = CreateTree(factors, factorCoefficients, @const);
-        if (tree == null) return factorTree;  
+        var factorTree = CreateTree(factors, factorCoefficients);
+        foreach (var binFactorNode in factorTree.IterateNodesPrefix().OfType<BinaryFactorVariableTreeNode>())
+          add.AddSubtree(binFactorNode);
       }
 
-      // Combine both trees
-      ISymbolicExpressionTreeNode add = tree.Root.GetSubtree(0).GetSubtree(0);
-      foreach (var binFactorNode in factorTree.IterateNodesPrefix().OfType<BinaryFactorVariableTreeNode>())
-        add.InsertSubtree(add.SubtreeCount - 1, binFactorNode);
+      if (@const!=0.0) {
+        ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+        cNode.Value = @const;
+        add.AddSubtree(cNode);
+      }
+
+      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
+      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
+      tree.Root.AddSubtree(startNode);
+      startNode.AddSubtree(add);
       return tree;
-
-      throw new ArgumentException();
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 16892)
@@ -51,12 +51,23 @@
     }
 
-    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+    /// <summary>
+    /// Produces an infix expression for a given expression tree.
+    /// </summary>
+    /// <param name="symbolicExpressionTree">The tree representation of the expression.</param>
+    /// <param name="numberFormat">Number format that should be used for numeric parameters (e.g. NumberFormatInfo.InvariantInfo (default)).</param>
+    /// <param name="formatString">The format string for numeric parameters (e.g. \"G4\" to limit to 4 digits, default is \"G\")</param>
+    /// <returns>Infix expression</returns>
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree, NumberFormatInfo numberFormat, string formatString="G") {
       // skip root and start symbols
       StringBuilder strBuilder = new StringBuilder();
-      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
+      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder, numberFormat, formatString);
       return strBuilder.ToString();
     }
 
-    private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      return Format(symbolicExpressionTree, NumberFormatInfo.InvariantInfo);
+    }
+
+    private static void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder, NumberFormatInfo numberFormat, string formatString) {
       if (node.SubtreeCount > 1) {
         var token = GetToken(node.Symbol);
@@ -66,9 +77,9 @@
             token == "^") {
           strBuilder.Append("(");
-          FormatRecursively(node.Subtrees.First(), strBuilder);
+          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString);
 
           foreach (var subtree in node.Subtrees.Skip(1)) {
             strBuilder.Append(" ").Append(token).Append(" ");
-            FormatRecursively(subtree, strBuilder);
+            FormatRecursively(subtree, strBuilder, numberFormat, formatString);
           }
           strBuilder.Append(")");
@@ -76,8 +87,8 @@
           // function with multiple arguments
           strBuilder.Append(token).Append("(");
-          FormatRecursively(node.Subtrees.First(), strBuilder);
+          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString);
           foreach (var subtree in node.Subtrees.Skip(1)) {
             strBuilder.Append(", ");
-            FormatRecursively(subtree, strBuilder);
+            FormatRecursively(subtree, strBuilder, numberFormat, formatString);
           }
           strBuilder.Append(")");
@@ -87,15 +98,15 @@
         if (token == "-" || token == "NOT") {
           strBuilder.Append("(").Append(token).Append("(");
-          FormatRecursively(node.GetSubtree(0), strBuilder);
+          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
           strBuilder.Append("))");
         } else if (token == "/") {
           strBuilder.Append("1/");
-          FormatRecursively(node.GetSubtree(0), strBuilder);
+          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
         } else if (token == "+" || token == "*") {
-          FormatRecursively(node.GetSubtree(0), strBuilder);
+          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
         } else {
           // function with only one argument
           strBuilder.Append(token).Append("(");
-          FormatRecursively(node.GetSubtree(0), strBuilder);
+          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
           strBuilder.Append(")");
         }
@@ -106,5 +117,5 @@
           if (!varNode.Weight.IsAlmost(1.0)) {
             strBuilder.Append("(");
-            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Weight);
+            strBuilder.Append(varNode.Weight.ToString(formatString, numberFormat));
             strBuilder.Append("*");
           }
@@ -116,5 +127,5 @@
           }
           strBuilder.Append(", ")
-            .AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Lag)
+            .AppendFormat(numberFormat, "{0}", varNode.Lag)
             .Append(")");
         } else if (node.Symbol is Variable) {
@@ -122,5 +133,5 @@
           if (!varNode.Weight.IsAlmost(1.0)) {
             strBuilder.Append("(");
-            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Weight);
+            strBuilder.Append(varNode.Weight.ToString(formatString, numberFormat));
             strBuilder.Append("*");
           }
@@ -141,10 +152,10 @@
           }
           strBuilder.AppendFormat("[{0}]",
-            string.Join(", ", factorNode.Weights.Select(w => w.ToString(CultureInfo.InvariantCulture))));
+            string.Join(", ", factorNode.Weights.Select(w => w.ToString(formatString, numberFormat))));
         } else if (node.Symbol is BinaryFactorVariable) {
           var factorNode = node as BinaryFactorVariableTreeNode;
           if (!factorNode.Weight.IsAlmost(1.0)) {
             strBuilder.Append("(");
-            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", factorNode.Weight);
+            strBuilder.Append(factorNode.Weight.ToString(formatString, numberFormat));
             strBuilder.Append("*");
           }
@@ -168,12 +179,12 @@
           var constNode = node as ConstantTreeNode;
           if (constNode.Value >= 0.0)
-            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", constNode.Value);
+            strBuilder.Append(constNode.Value.ToString(formatString, numberFormat));
           else
-            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "({0})", constNode.Value); // (-1
+            strBuilder.Append("(").Append(constNode.Value.ToString(formatString, numberFormat)).Append(")"); // (-1
         }
       }
     }
 
-    private string GetToken(ISymbol symbol) {
+    private static string GetToken(ISymbol symbol) {
       var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).FirstOrDefault();
       if (tok == null)
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 16892)
@@ -26,8 +26,8 @@
 using System.Text;
 using System.Text.RegularExpressions;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -56,5 +56,5 @@
     }
 
-    private string VariableName2Identifier(string name) {     
+    private string VariableName2Identifier(string name) {
       /*
        * identifier-start-character:
@@ -131,12 +131,26 @@
         } else if (node.Symbol is Tangent) {
           FormatFunction(node, "Math.Tan", strBuilder);
+        } else if (node.Symbol is HyperbolicTangent) {
+          FormatFunction(node, "Math.Tanh", strBuilder);
         } else if (node.Symbol is Square) {
           FormatSquare(node, strBuilder);
         } else if (node.Symbol is SquareRoot) {
           FormatFunction(node, "Math.Sqrt", strBuilder);
+        } else if (node.Symbol is Cube) {
+          FormatPower(node, strBuilder, "3");
+        } else if (node.Symbol is CubeRoot) {
+          FormatPower(node, strBuilder, "1.0/3");
         } else if (node.Symbol is Power) {
           FormatFunction(node, "Math.Pow", strBuilder);
         } else if (node.Symbol is Root) {
           FormatRoot(node, strBuilder);
+        } else if (node.Symbol is Absolute) {
+          FormatFunction(node, "Math.Abs", strBuilder);
+        } else if (node.Symbol is AnalyticQuotient) {
+          strBuilder.Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(" / Math.Sqrt(1 + Math.Pow(");
+          FormatRecursively(node.GetSubtree(1), strBuilder);
+          strBuilder.Append(" , 2) )");
         } else {
           throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for C# symbolic expression tree formatter.");
@@ -171,7 +185,10 @@
 
     private void FormatSquare(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      FormatPower(node, strBuilder, "2");
+    }
+    private void FormatPower(ISymbolicExpressionTreeNode node, StringBuilder strBuilder, string exponent) {
       strBuilder.Append("Math.Pow(");
       FormatRecursively(node.GetSubtree(0), strBuilder);
-      strBuilder.Append(", 2)");
+      strBuilder.Append($", {exponent})");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs	(revision 16892)
@@ -25,8 +25,8 @@
 using System.Linq;
 using System.Text;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -119,6 +119,10 @@
         }
         stringBuilder.Append(")");
+      } else if (symbol is Absolute) {
+        stringBuilder.Append($"ABS({FormatRecursively(node.GetSubtree(0))})");
+      } else if (symbol is AnalyticQuotient) {
+        stringBuilder.Append($"({FormatRecursively(node.GetSubtree(0))}) / SQRT(1 + POWER({FormatRecursively(node.GetSubtree(1))}, 2))");
       } else if (symbol is Average) {
-        stringBuilder.Append("(1/");
+        stringBuilder.Append("(1/(");
         stringBuilder.Append(node.SubtreeCount);
         stringBuilder.Append(")*(");
@@ -129,5 +133,5 @@
           stringBuilder.Append(")");
         }
-        stringBuilder.Append(")");
+        stringBuilder.Append("))");
       } else if (symbol is Constant) {
         ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
@@ -137,8 +141,13 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(")");
+      } else if (symbol is Cube) {
+        stringBuilder.Append($"POWER({FormatRecursively(node.GetSubtree(0))}, 3)");
+      } else if (symbol is CubeRoot) {
+        stringBuilder.Append($"POWER({FormatRecursively(node.GetSubtree(0))}, 1/3)");
       } else if (symbol is Division) {
         if (node.SubtreeCount == 1) {
-          stringBuilder.Append("1/");
-          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+          stringBuilder.Append("1/(");
+          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+          stringBuilder.Append(")");
         } else {
           stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
@@ -192,5 +201,8 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(")");
-
+      } else if (symbol is HyperbolicTangent) {
+        stringBuilder.Append("TANH(");
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+        stringBuilder.Append(")");
       } else if (symbol is Variable) {
         VariableTreeNode variableTreeNode = node as VariableTreeNode;
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 16892)
@@ -24,8 +24,8 @@
 using System.Linq;
 using System.Text;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -117,4 +117,8 @@
           strBuilder.Append(@" \cfrac{ ");
         }
+      } else if (node.Symbol is Absolute) {
+        strBuilder.Append(@"\operatorname{abs} \left( ");
+      } else if (node.Symbol is AnalyticQuotient) {
+        strBuilder.Append(@" \frac { ");
       } else if (node.Symbol is Average) {
         // skip output of (1/1) if only one subtree
@@ -131,4 +135,8 @@
       } else if (node.Symbol is SquareRoot) {
         strBuilder.Append(@"\sqrt{");
+      } else if (node.Symbol is Cube) {
+        strBuilder.Append(@"\left(");
+      } else if (node.Symbol is CubeRoot) {
+        strBuilder.Append(@"\left(");
       } else if (node.Symbol is Sine) {
         strBuilder.Append(@"\sin \left( ");
@@ -137,4 +145,6 @@
       } else if (node.Symbol is Tangent) {
         strBuilder.Append(@"\tan \left( ");
+      } else if (node.Symbol is HyperbolicTangent) {
+        strBuilder.Append(@"\tanh \left( ");
       } else if (node.Symbol is AiryA) {
         strBuilder.Append(@"\operatorname{airy}_a \left( ");
@@ -287,4 +297,8 @@
         else
           strBuilder.Append(@" }{ \cfrac{ ");
+      } else if (node.Symbol is Absolute) {
+        throw new InvalidOperationException();
+      } else if (node.Symbol is AnalyticQuotient) {
+        strBuilder.Append(@"}{\sqrt{1 + \left( ");
       } else if (node.Symbol is Average) {
         strBuilder.Append(@" + ");
@@ -297,4 +311,8 @@
       } else if (node.Symbol is SquareRoot) {
         throw new InvalidOperationException();
+      } else if (node.Symbol is Cube) {
+        throw new InvalidOperationException();
+      } else if (node.Symbol is CubeRoot) {
+        throw new InvalidOperationException();
       } else if (node.Symbol is Sine) {
         throw new InvalidOperationException();
@@ -302,4 +320,6 @@
         throw new InvalidOperationException();
       } else if (node.Symbol is Tangent) {
+        throw new InvalidOperationException();
+      } else if (node.Symbol is HyperbolicTangent) {
         throw new InvalidOperationException();
       } else if (node.Symbol is AiryA) {
@@ -383,4 +403,8 @@
         for (int i = 2; i < node.SubtreeCount; i++)
           strBuilder.Append(" } ");
+      } else if (node.Symbol is Absolute) {
+        strBuilder.Append(@" \right)");
+      } else if (node.Symbol is AnalyticQuotient) {
+        strBuilder.Append(@" \right)^2}}");
       } else if (node.Symbol is Average) {
         strBuilder.Append(@" \right) ");
@@ -393,4 +417,8 @@
       } else if (node.Symbol is SquareRoot) {
         strBuilder.Append(@"}");
+      } else if (node.Symbol is Cube) {
+        strBuilder.Append(@"\right)^3");
+      } else if (node.Symbol is CubeRoot) {
+        strBuilder.Append(@"\right)^\frac{1}{3}");
       } else if (node.Symbol is Sine) {
         strBuilder.Append(@" \right) ");
@@ -398,4 +426,6 @@
         strBuilder.Append(@" \right) ");
       } else if (node.Symbol is Tangent) {
+        strBuilder.Append(@" \right) ");
+      } else if (node.Symbol is HyperbolicTangent) {
         strBuilder.Append(@" \right) ");
       } else if (node.Symbol is AiryA) {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs	(revision 16892)
@@ -23,8 +23,8 @@
 using System.Linq;
 using System.Text;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -126,4 +126,8 @@
         }
         stringBuilder.Append(")");
+      } else if (symbol is Absolute) {
+        stringBuilder.Append($"abs({FormatRecursively(node.GetSubtree(0))})");
+      } else if (symbol is AnalyticQuotient) {
+        stringBuilder.Append($"({FormatRecursively(node.GetSubtree(0))}) / sqrt(1 + ({FormatRecursively(node.GetSubtree(1))}).^2)");
       } else if (symbol is And) {
         stringBuilder.Append("((");
@@ -179,4 +183,12 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(")");
+      } else if (symbol is Cube) {
+        stringBuilder.Append("(");
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+        stringBuilder.Append(").^3");
+      } else if (symbol is CubeRoot) {
+        stringBuilder.Append("(");
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+        stringBuilder.Append(").^(1/3)");
       } else if (symbol is GreaterThan) {
         stringBuilder.Append("((");
@@ -252,4 +264,8 @@
       } else if (symbol is Tangent) {
         stringBuilder.Append("tan(");
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+        stringBuilder.Append(")");
+      } else if (symbol is HyperbolicTangent) {
+        stringBuilder.Append("tanh(");
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(")");
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 16892)
@@ -24,8 +24,8 @@
 using System.Linq;
 using System.Text;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
@@ -56,4 +56,12 @@
         if (node.Symbol is Addition) {
           FormatFunction(node, "Plus", strBuilder);
+        } else if (node.Symbol is Absolute) {
+          FormatFunction(node, "Abs", strBuilder);
+        } else if (node.Symbol is AnalyticQuotient) {
+          strBuilder.Append("[");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append("]/Sqrt[ 1 + Power[");
+          FormatRecursively(node.GetSubtree(1), strBuilder);
+          strBuilder.Append(", 2]]");
         } else if (node.Symbol is Average) {
           FormatAverage(node, strBuilder);
@@ -70,4 +78,6 @@
         } else if (node.Symbol is Tangent) {
           FormatFunction(node, "Tan", strBuilder);
+        } else if (node.Symbol is HyperbolicTangent) {
+          FormatFunction(node, "Tanh", strBuilder);
         } else if (node.Symbol is Exponential) {
           FormatFunction(node, "Exp", strBuilder);
@@ -102,4 +112,8 @@
         } else if (node.Symbol is SquareRoot) {
           FormatFunction(node, "Sqrt", strBuilder);
+        } else if (node.Symbol is Cube) {
+          FormatPower(node, strBuilder, "3");
+        } else if (node.Symbol is CubeRoot) {
+          FormatPower(node, strBuilder, "1/3");
         } else if (node.Symbol is Power) {
           FormatFunction(node, "Power", strBuilder);
@@ -203,7 +217,11 @@
 
     private void FormatSquare(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      FormatPower(node, strBuilder, "2");
+    }
+
+    private void FormatPower(ISymbolicExpressionTreeNode node, StringBuilder strBuilder, string exponent) {
       strBuilder.Append("Power[");
       FormatRecursively(node.GetSubtree(0), strBuilder);
-      strBuilder.Append(", 2]");
+      strBuilder.Append($", {exponent}]");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs	(revision 16892)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Globalization;
 using System.Text;
@@ -69,4 +70,8 @@
         }
         stringBuilder.Append(") ifTrue:[1] ifFalse:[-1]");
+      } else if (symbol is Absolute) {
+        stringBuilder.Append($"({FormatRecursively(node.GetSubtree(0))}) abs");
+      } else if (symbol is AnalyticQuotient) {
+        stringBuilder.Append($"({FormatRecursively(node.GetSubtree(0))}) / (1 + ({FormatPower(node.GetSubtree(1), "2")})) sqrt");
       } else if (symbol is Average) {
         stringBuilder.Append("(1/");
@@ -84,4 +89,8 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(" cos");
+      } else if (symbol is Cube) {
+        stringBuilder.Append(FormatPower(node.GetSubtree(0), "3"));
+      } else if (symbol is CubeRoot) {
+        stringBuilder.Append(FormatPower(node.GetSubtree(0), "(1/3)"));
       } else if (symbol is Division) {
         if (node.SubtreeCount == 1) {
@@ -146,4 +155,8 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(" sin");
+      } else if (symbol is Square) {
+        stringBuilder.Append(FormatPower(node.GetSubtree(0), "2"));
+      } else if (symbol is SquareRoot) {
+        stringBuilder.Append(FormatPower(node.GetSubtree(0), "(1/2)"));
       } else if (symbol is Subtraction) {
         if (node.SubtreeCount == 1) {
@@ -160,4 +173,7 @@
         stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
         stringBuilder.Append(" tan");
+      } else if (symbol is HyperbolicTangent) {
+        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
+        stringBuilder.Append(" tanh");
       } else if (symbol is Variable) {
         VariableTreeNode variableTreeNode = node as VariableTreeNode;
@@ -181,4 +197,8 @@
     }
 
+    private string FormatPower(ISymbolicExpressionTreeNode node, string exponent) {
+      return $"(({FormatRecursively(node)}) log * {exponent}) exp ";
+    }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SymbolicDataAnalysisExpressionSmalltalkFormatter(this, cloner);
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 16892)
@@ -106,4 +106,8 @@
       <HintPath>..\..\bin\AutoDiff-1.0.dll</HintPath>
       <Private>False</Private>
+    </Reference>
+    <Reference Include="HEAL.Attic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\bin\HEAL.Attic.dll</HintPath>
     </Reference>
     <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic.NativeInterpreter-0.1, Version=0.0.0.1, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
@@ -404,12 +408,4 @@
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup>
-    <PackageReference Include="HEAL.Attic">
-      <Version>1.0.0-pre03</Version>
-    </PackageReference>
-    <PackageReference Include="System.Numerics.Vectors">
-      <Version>4.5.0</Version>
-    </PackageReference>
-  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs	(revision 16892)
@@ -69,16 +69,16 @@
     #endregion
 
-    public Interval GetSymbolicExressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
+    public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
       var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
-      return GetSymbolicExressionTreeInterval(tree, variableRanges);
-    }
-
-    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
-      out Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) {
+      return GetSymbolicExpressionTreeInterval(tree, variableRanges);
+    }
+
+    public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
+      out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) {
       var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
-      return GetSymbolicExressionTreeIntervals(tree, variableRanges, out nodeIntervals);
-    }
-
-    public Interval GetSymbolicExressionTreeInterval(ISymbolicExpressionTree tree, Dictionary<string, Interval> variableRanges) {
+      return GetSymbolicExpressionTreeIntervals(tree, variableRanges, out nodeIntervals);
+    }
+
+    public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IDictionary<string, Interval> variableRanges) {
       lock (syncRoot) {
         EvaluatedSolutions++;
@@ -96,6 +96,6 @@
 
 
-    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree,
-      Dictionary<string, Interval> variableRanges, out Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals) {
+    public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree,
+      IDictionary<string, Interval> variableRanges, out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals) {
       lock (syncRoot) {
         EvaluatedSolutions++;
@@ -108,5 +108,5 @@
       // fix incorrect intervals if necessary (could occur because of numerical errors)
       nodeIntervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
-      foreach(var kvp in intervals) {
+      foreach (var kvp in intervals) {
         var interval = kvp.Value;
         if (interval.IsInfiniteOrUndefined || interval.LowerBound <= interval.UpperBound)
@@ -124,5 +124,5 @@
 
 
-    private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, Dictionary<string, Interval> variableRanges) {
+    private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, IDictionary<string, Interval> variableRanges) {
       if (variableRanges == null)
         throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges));
@@ -141,5 +141,5 @@
     }
 
-    private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, Dictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) {
+    private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) {
       Instruction currentInstr = instructions[instructionCounter];
       //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
@@ -216,4 +216,9 @@
             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
             result = Interval.Tangens(argumentInterval);
+            break;
+          }
+        case OpCodes.Tanh: {
+            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
+            result = Interval.HyperbolicTangent(argumentInterval);
             break;
           }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs	(revision 16892)
@@ -22,73 +22,116 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public enum OpCode : byte {
+    Add = 1,
+    Sub = 2,
+    Mul = 3,
+    Div = 4,
+    Sin = 5,
+    Cos = 6,
+    Tan = 7,
+    Log = 8,
+    Exp = 9,
+    IfThenElse = 10,
+    GT = 11,
+    LT = 12,
+    AND = 13,
+    OR = 14,
+    NOT = 15,
+    Average = 16,
+    Call = 17,
+    Variable = 18,
+    LagVariable = 19,
+    Constant = 20,
+    Arg = 21,
+    Power = 22,
+    Root = 23,
+    TimeLag = 24,
+    Integral = 25,
+    Derivative = 26,
+    VariableCondition = 27,
+    Square = 28,
+    SquareRoot = 29,
+    Gamma = 30,
+    Psi = 31,
+    Dawson = 32,
+    ExponentialIntegralEi = 33,
+    CosineIntegral = 34,
+    SineIntegral = 35,
+    HyperbolicCosineIntegral = 36,
+    HyperbolicSineIntegral = 37,
+    FresnelCosineIntegral = 38,
+    FresnelSineIntegral = 39,
+    AiryA = 40,
+    AiryB = 41,
+    Norm = 42,
+    Erf = 43,
+    Bessel = 44,
+    XOR = 45,
+    FactorVariable = 46,
+    BinaryFactorVariable = 47,
+    Absolute = 48,
+    AnalyticQuotient = 49,
+    Cube = 50,
+    CubeRoot = 51,
+    Tanh = 52,
+  };
   public static class OpCodes {
-    public const byte Add = 1;
-    public const byte Sub = 2;
-    public const byte Mul = 3;
-    public const byte Div = 4;
-
-    public const byte Sin = 5;
-    public const byte Cos = 6;
-    public const byte Tan = 7;
-
-    public const byte Log = 8;
-    public const byte Exp = 9;
-
-    public const byte IfThenElse = 10;
-
-    public const byte GT = 11;
-    public const byte LT = 12;
-
-    public const byte AND = 13;
-    public const byte OR = 14;
-    public const byte NOT = 15;
-
-
-    public const byte Average = 16;
-
-    public const byte Call = 17;
-
-    public const byte Variable = 18;
-    public const byte LagVariable = 19;
-    public const byte Constant = 20;
-    public const byte Arg = 21;
-
-    public const byte Power = 22;
-    public const byte Root = 23;
-    public const byte TimeLag = 24;
-    public const byte Integral = 25;
-    public const byte Derivative = 26;
-
-    public const byte VariableCondition = 27;
-
-    public const byte Square = 28;
-    public const byte SquareRoot = 29;
-    public const byte Gamma = 30;
-    public const byte Psi = 31;
-    public const byte Dawson = 32;
-    public const byte ExponentialIntegralEi = 33;
-    public const byte CosineIntegral = 34;
-    public const byte SineIntegral = 35;
-    public const byte HyperbolicCosineIntegral = 36;
-    public const byte HyperbolicSineIntegral = 37;
-    public const byte FresnelCosineIntegral = 38;
-    public const byte FresnelSineIntegral = 39;
-    public const byte AiryA = 40;
-    public const byte AiryB = 41;
-    public const byte Norm = 42;
-    public const byte Erf = 43;
-    public const byte Bessel = 44;
-    public const byte XOR = 45;
-    public const byte FactorVariable = 46;
-    public const byte BinaryFactorVariable = 47;
-    public const byte Absolute = 48;
-    public const byte AnalyticQuotient = 49;
-    public const byte Cube = 50;
-    public const byte CubeRoot = 51;
-
-    public const byte Tanh = 52;
+    // constants for API compatibility only
+    public const byte Add = (byte)OpCode.Add;
+    public const byte Sub =(byte)OpCode.Sub;
+    public const byte Mul =(byte)OpCode.Mul;
+    public const byte Div =(byte)OpCode.Div;
+    public const byte Sin =(byte)OpCode.Sin;
+    public const byte Cos =(byte)OpCode.Cos;
+    public const byte Tan =(byte)OpCode.Tan;
+    public const byte Log =(byte)OpCode.Log;
+    public const byte Exp = (byte)OpCode.Exp;
+    public const byte IfThenElse = (byte)OpCode.IfThenElse;
+    public const byte GT = (byte)OpCode.GT;
+    public const byte LT = (byte)OpCode.LT;
+    public const byte AND = (byte)OpCode.AND;
+    public const byte OR = (byte)OpCode.OR;
+    public const byte NOT = (byte)OpCode.NOT;
+    public const byte Average = (byte)OpCode.Average;
+    public const byte Call = (byte)OpCode.Call;
+    public const byte Variable = (byte)OpCode.Variable;
+    public const byte LagVariable = (byte)OpCode.LagVariable;
+    public const byte Constant = (byte)OpCode.Constant;
+    public const byte Arg = (byte)OpCode.Arg;
+    public const byte Power = (byte)OpCode.Power;
+    public const byte Root = (byte)OpCode.Root;
+    public const byte TimeLag = (byte)OpCode.TimeLag;
+    public const byte Integral = (byte)OpCode.Integral;
+    public const byte Derivative = (byte)OpCode.Derivative;
+    public const byte VariableCondition = (byte)OpCode.VariableCondition;
+    public const byte Square = (byte)OpCode.Square;
+    public const byte SquareRoot = (byte)OpCode.SquareRoot;
+    public const byte Gamma = (byte)OpCode.Gamma;
+    public const byte Psi = (byte)OpCode.Psi;
+    public const byte Dawson = (byte)OpCode.Dawson;
+    public const byte ExponentialIntegralEi = (byte)OpCode.ExponentialIntegralEi;
+    public const byte CosineIntegral = (byte)OpCode.CosineIntegral;
+    public const byte SineIntegral = (byte)OpCode.SineIntegral;
+    public const byte HyperbolicCosineIntegral = (byte)OpCode.HyperbolicCosineIntegral;
+    public const byte HyperbolicSineIntegral = (byte)OpCode.HyperbolicSineIntegral;
+    public const byte FresnelCosineIntegral = (byte)OpCode.FresnelCosineIntegral;
+    public const byte FresnelSineIntegral = (byte)OpCode.FresnelSineIntegral;
+    public const byte AiryA = (byte)OpCode.AiryA;
+    public const byte AiryB = (byte)OpCode.AiryB;
+    public const byte Norm = (byte)OpCode.Norm;
+    public const byte Erf = (byte)OpCode.Erf;
+    public const byte Bessel = (byte)OpCode.Bessel;
+    public const byte XOR = (byte)OpCode.XOR;
+    public const byte FactorVariable = (byte)OpCode.FactorVariable;
+    public const byte BinaryFactorVariable = (byte)OpCode.BinaryFactorVariable;
+    public const byte Absolute = (byte)OpCode.Absolute;
+    public const byte AnalyticQuotient = (byte)OpCode.AnalyticQuotient;
+    public const byte Cube = (byte)OpCode.Cube;
+    public const byte CubeRoot = (byte)OpCode.CubeRoot;
+    public const byte Tanh = (byte)OpCode.Tanh;
 
 
@@ -150,6 +193,5 @@
 
     public static byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {
-      byte opCode;
-      if (symbolToOpcode.TryGetValue(treeNode.Symbol.GetType(), out opCode)) return opCode;
+      if (symbolToOpcode.TryGetValue(treeNode.Symbol.GetType(), out byte opCode)) return opCode;
       else throw new NotSupportedException("Symbol: " + treeNode.Symbol);
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 16892)
@@ -45,4 +45,5 @@
     private static readonly MethodInfo Cos = typeof(Math).GetMethod("Cos", new[] { typeof(double) });
     private static readonly MethodInfo Tan = typeof(Math).GetMethod("Tan", new[] { typeof(double) });
+    private static readonly MethodInfo Tanh = typeof(Math).GetMethod("Tanh", new[] { typeof(double) });
     private static readonly MethodInfo Sqrt = typeof(Math).GetMethod("Sqrt", new[] { typeof(double) });
     private static readonly MethodInfo Floor = typeof(Math).GetMethod("Floor", new[] { typeof(double) });
@@ -223,4 +224,8 @@
             return Expression.Call(Tan, arg);
           }
+        case OpCodes.Tanh: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Tanh, arg);
+          }
         case OpCodes.Square: {
             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs	(revision 16892)
@@ -63,5 +63,5 @@
               break;
             }
-
+          case OpCodes.Constant: break; // nothing to do here, don't remove because we want to prevent falling into the default case here.
           case OpCodes.Add: {
               Load(instr.buf, code[c].buf);
@@ -173,4 +173,5 @@
               break;
             }
+          default: throw new NotSupportedException($"This interpreter does not support {(OpCode)instr.opcode}");
         }
       }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 16892)
@@ -45,4 +45,5 @@
     private static MethodInfo sin = typeof(Math).GetMethod("Sin", new Type[] { typeof(double) });
     private static MethodInfo tan = typeof(Math).GetMethod("Tan", new Type[] { typeof(double) });
+    private static MethodInfo tanh = typeof(Math).GetMethod("Tanh", new Type[] { typeof(double) });
     private static MethodInfo exp = typeof(Math).GetMethod("Exp", new Type[] { typeof(double) });
     private static MethodInfo log = typeof(Math).GetMethod("Log", new Type[] { typeof(double) });
@@ -283,4 +284,9 @@
             CompileInstructions(il, state, ds);
             il.Emit(System.Reflection.Emit.OpCodes.Call, tan);
+            return;
+          }
+        case OpCodes.Tanh: {
+            CompileInstructions(il, state, ds);
+            il.Emit(System.Reflection.Emit.OpCodes.Call, tanh);
             return;
           }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs	(revision 16892)
@@ -101,4 +101,27 @@
     private IDataset dataset;
 
+    private static readonly HashSet<byte> supportedOpCodes = new HashSet<byte>() {
+      (byte)OpCode.Constant,
+      (byte)OpCode.Variable,
+      (byte)OpCode.Add,
+      (byte)OpCode.Sub,
+      (byte)OpCode.Mul,
+      (byte)OpCode.Div,
+      (byte)OpCode.Exp,
+      (byte)OpCode.Log,
+      (byte)OpCode.Sin,
+      (byte)OpCode.Cos,
+      (byte)OpCode.Tan,
+      (byte)OpCode.Tanh,
+      (byte)OpCode.Power,
+      (byte)OpCode.Root,
+      (byte)OpCode.SquareRoot,
+      (byte)OpCode.Square,
+      (byte)OpCode.CubeRoot,
+      (byte)OpCode.Cube,
+      (byte)OpCode.Absolute,
+      (byte)OpCode.AnalyticQuotient
+    };
+
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
       if (!rows.Any()) return Enumerable.Empty<double>();
@@ -108,5 +131,10 @@
       }
 
-      var code = Compile(tree, OpCodes.MapSymbolToOpCode);
+      byte mapSupportedSymbols(ISymbolicExpressionTreeNode node) {        
+        var opCode = OpCodes.MapSymbolToOpCode(node);
+        if (supportedOpCodes.Contains(opCode)) return opCode;
+        else throw new NotSupportedException($"The native interpreter does not support {node.Symbol.Name}");
+      };
+      var code = Compile(tree, mapSupportedSymbols);
 
       var rowsArray = rows.ToArray();
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Selectors/DiversitySelector.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Selectors/DiversitySelector.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Selectors/DiversitySelector.cs	(revision 16892)
@@ -100,6 +100,14 @@
     #region Events
     private void RegisterParameterEventHandlers() {
-      SelectorParameter.ValueChanged += new EventHandler(SelectorParameter_ValueChanged);
-      CopySelected.ValueChanged += new EventHandler(CopySelected_ValueChanged);
+      SelectorParameter.ValueChanged += SelectorParameter_ValueChanged;
+      CopySelectedParameter.ValueChanged += CopySelectedParameter_ValueChanged;
+      CopySelected.ValueChanged += CopySelected_ValueChanged;
+    }
+
+    private void CopySelectedParameter_ValueChanged(object sender, EventArgs e) {
+      if (CopySelected.Value != true) {
+        CopySelected.Value = true;
+      }
+      CopySelected.ValueChanged += CopySelected_ValueChanged;
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 16892)
@@ -25,8 +25,8 @@
 using System.Collections.ObjectModel;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -115,4 +115,42 @@
     }
 
+    public static Dataset FromRowData(IEnumerable<string> variableNames, double[,] data) {
+      var colWise = new List<IList>(data.GetLength(1));
+      for (var col = 0; col < data.GetLength(1); col++) {
+        var column = new List<double>(data.GetLength(0));
+        for (var row = 0; row < data.GetLength(0); row++) {
+          column.Add(data[row, col]);
+        }
+        colWise.Add(column);
+      }
+      return new Dataset(variableNames, colWise);
+    }
+
+    public static Dataset FromRowData(IEnumerable<string> variableNames, IEnumerable<IList> data) {
+      var vnames = variableNames.ToList();
+      var transposed = new List<IList>();
+      var iter = data.GetEnumerator();
+      if (!iter.MoveNext()) throw new ArgumentException("Data does not contain any rows", nameof(data));
+      for (var i = 0; i < iter.Current.Count; i++) {
+        if (i >= vnames.Count) throw new ArgumentException("There are more variables in data, than variable names.", nameof(variableNames));
+        if (iter.Current[i] == null) throw new ArgumentException("Null values are not supported.", nameof(data));
+        if (!IsAllowedType(iter.Current[i].GetType())) throw new ArgumentException("Data contains types that are not allowed.", nameof(data));
+        if (iter.Current[i] is double d)
+          transposed.Add(new List<double>() { d });
+        else if (iter.Current[i] is DateTime dt)
+          transposed.Add(new List<DateTime>() { dt });
+        else if (iter.Current[i] is string s)
+          transposed.Add(new List<string>() { s });
+        else throw new NotSupportedException(string.Format("Variable {0} has type {1}. This is not supported when converting from row-wise data.", vnames[i], iter.Current[i].GetType()));
+      }
+      if (transposed.Count < vnames.Count) throw new ArgumentException("There are less variables in data, than variable names.", nameof(variableNames));
+      while (iter.MoveNext()) {
+        for (var i = 0; i < iter.Current.Count; i++)
+          if (transposed[i].Add(iter.Current[i]) < 0)
+            throw new ArgumentException(string.Format("Variable {0} has invalid value ({1})", vnames[i], iter.Current[i]), nameof(data));
+      }
+      return new Dataset(vnames, transposed);
+    }
+
     public ModifiableDataset ToModifiable() {
       return new ModifiableDataset(variableNames, variableNames.Select(v => variableValues[v]), true);
@@ -133,6 +171,6 @@
     #region Backwards compatible code, remove with 3.5
     private double[,] storableData;
-    //name alias used to suppport backwards compatibility
-    [Storable(Name = "data", AllowOneWay = true)]
+    //name alias used to support backwards compatibility
+    [Storable(OldName = "data")]
     private double[,] StorableData { set { storableData = value; } }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 16892)
@@ -244,4 +244,5 @@
     <Compile Include="OnlineCalculators\OnlineTheilsUStatisticCalculator.cs" />
     <Compile Include="OnlineCalculators\OnlineWeightedDirectionalSymmetryCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlineWeightedClassificationMeanSquaredErrorCalculator.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Implementation\Classification\ThresholdCalculators\AccuracyMaximizationThresholdCalculator.cs" />
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationModel.cs	(revision 16892)
@@ -75,5 +75,5 @@
       var classificationProblemData = problemData as IClassificationProblemData;
       if (classificationProblemData == null)
-        throw new ArgumentException("The problem data is not a regression problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+        throw new ArgumentException("The problem data is not compatible with this classification model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
       return IsProblemDataCompatible(classificationProblemData, out errorMessage);
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 16892)
@@ -23,7 +23,7 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -121,6 +121,11 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
+      var estimatedValues = GetEstimatedValues(dataset, rows);
+      return GetEstimatedClassValues(estimatedValues);
+    }
+
+    public virtual IEnumerable<double> GetEstimatedClassValues(IEnumerable<double> estimatedValues) {
       if (!Thresholds.Any() && !ClassValues.Any()) throw new ArgumentException("No thresholds and class values were set for the current classification model.");
-      foreach (var x in GetEstimatedValues(dataset, rows)) {
+      foreach (var x in estimatedValues) {
         int classIndex = 0;
         // find first threshold value which is larger than x => class index = threshold index + 1
@@ -132,4 +137,5 @@
       }
     }
+
     #region events
     public event EventHandler ThresholdsChanged;
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/ConstantModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/ConstantModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/ConstantModel.cs	(revision 16892)
@@ -98,5 +98,5 @@
         return IsProblemDataCompatible(classificationProblemData, out errorMessage);
 
-      throw new ArgumentException("The problem data is not a regression nor a classification problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+      throw new ArgumentException("The problem data is compatible with this model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval.cs	(revision 16892)
@@ -167,8 +167,11 @@
     }
     public static Interval Cosine(Interval a) {
-      return Interval.Sine(Interval.Subtract(a, new Interval(Math.PI / 2, Math.PI / 2)));
+      return Interval.Sine(Interval.Add(a, new Interval(Math.PI / 2, Math.PI / 2)));
     }
     public static Interval Tangens(Interval a) {
       return Interval.Divide(Interval.Sine(a), Interval.Cosine(a));
+    }  
+    public static Interval HyperbolicTangent(Interval a) {
+      return new Interval(Math.Tanh(a.LowerBound), Math.Tanh(a.UpperBound));
     }
 
@@ -203,5 +206,5 @@
       if (a.UpperBound <= 0) return new Interval(a.UpperBound * a.UpperBound, a.LowerBound * a.LowerBound);     // interval is negative
       else if (a.LowerBound >= 0) return new Interval(a.LowerBound * a.LowerBound, a.UpperBound * a.UpperBound); // interval is positive
-      else return new Interval(0, Math.Max(a.LowerBound*a.LowerBound, a.UpperBound*a.UpperBound)); // interval goes over zero
+      else return new Interval(0, Math.Max(a.LowerBound * a.LowerBound, a.UpperBound * a.UpperBound)); // interval goes over zero
     }
 
@@ -224,5 +227,5 @@
     public static Interval CubicRoot(Interval a) {
       if (a.LowerBound < 0) return new Interval(double.NaN, double.NaN);
-      return new Interval(Math.Pow(a.LowerBound, 1.0/3), Math.Pow(a.UpperBound, 1.0/3));
+      return new Interval(Math.Pow(a.LowerBound, 1.0 / 3), Math.Pow(a.UpperBound, 1.0 / 3));
     }
     #endregion
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 16892)
@@ -73,5 +73,5 @@
 
     #region backwards compatiblity 3.3.5
-    [Storable(Name = "models", AllowOneWay = true)]
+    [Storable(OldName = "models")]
     private List<IRegressionModel> OldStorableModels {
       set { models = value; }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionModel.cs	(revision 16892)
@@ -76,5 +76,5 @@
       var regressionProblemData = problemData as IRegressionProblemData;
       if (regressionProblemData == null)
-        throw new ArgumentException("The problem data is not a regression problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+        throw new ArgumentException("The problem data is not compatible with this regression model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
       return IsProblemDataCompatible(regressionProblemData, out errorMessage);
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 16892)
@@ -34,4 +34,5 @@
     void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues);
     IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows);
+    IEnumerable<double> GetEstimatedClassValues(IEnumerable<double> estimatedValues);
 
     event EventHandler ThresholdsChanged;
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedClassificationMeanSquaredErrorCalculator.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedClassificationMeanSquaredErrorCalculator.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedClassificationMeanSquaredErrorCalculator.cs	(revision 16892)
@@ -0,0 +1,115 @@
+﻿#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 HeuristicLab.Common;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineWeightedClassificationMeanSquaredErrorCalculator : IOnlineCalculator {
+
+    private double sse;
+    private int n;
+    public double WeightedResidualsMeanSquaredError {
+      get {
+        return n > 0 ? sse / n : 0.0;
+      }
+    }
+
+    public double PositiveClassValue { get; private set; }
+    public double ClassValuesMax { get; private set; }
+    public double ClassValuesMin { get; private set; }
+    public double DefiniteResidualsWeight { get; private set; }
+    public double PositiveClassResidualsWeight { get; private set; }
+    public double NegativeClassesResidualsWeight { get; private set; }
+
+    public OnlineWeightedClassificationMeanSquaredErrorCalculator(double positiveClassValue, double classValuesMax, double classValuesMin,
+                                                                double definiteResidualsWeight, double positiveClassResidualsWeight, double negativeClassesResidualsWeight) {
+      PositiveClassValue = positiveClassValue;
+      ClassValuesMax = classValuesMax;
+      ClassValuesMin = classValuesMin;
+      DefiniteResidualsWeight = definiteResidualsWeight;
+      PositiveClassResidualsWeight = positiveClassResidualsWeight;
+      NegativeClassesResidualsWeight = negativeClassesResidualsWeight;
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError ErrorState {
+      get { return errorState; }
+    }
+    public double Value {
+      get { return WeightedResidualsMeanSquaredError; }
+    }
+    public void Reset() {
+      n = 0;
+      sse = 0.0;
+      errorState = OnlineCalculatorError.InsufficientElementsAdded;
+    }
+
+    public void Add(double original, double estimated) {
+      if (double.IsNaN(estimated) || double.IsInfinity(estimated) ||
+          double.IsNaN(original) || double.IsInfinity(original) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
+        errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
+      } else {
+        double error = estimated - original;
+        double weight;
+        //apply weight
+        if (estimated > ClassValuesMax || estimated < ClassValuesMin) {
+          weight = DefiniteResidualsWeight;
+        } else if (original.IsAlmost(PositiveClassValue)) {
+          weight = PositiveClassResidualsWeight;
+        } else {
+          weight = NegativeClassesResidualsWeight;
+        }
+        sse += error * error * weight;
+        n++;
+        errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
+      }
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, double positiveClassValue, double classValuesMax, double classValuesMin,
+                                                                double definiteResidualsWeight, double positiveClassResidualsWeight, double negativeClassesResidualsWeight, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineWeightedClassificationMeanSquaredErrorCalculator calculator = new OnlineWeightedClassificationMeanSquaredErrorCalculator(positiveClassValue, classValuesMax, classValuesMin, definiteResidualsWeight, positiveClassResidualsWeight, negativeClassesResidualsWeight);
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        calculator.Add(original, estimated);
+        if (calculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (calculator.ErrorState == OnlineCalculatorError.None &&
+         (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
+      } else {
+        errorState = calculator.ErrorState;
+        return calculator.WeightedResidualsMeanSquaredError;
+      }
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/ArtificialAnt/Problem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/ArtificialAnt/Problem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/ArtificialAnt/Problem.cs	(revision 16892)
@@ -23,4 +23,5 @@
 using System.Diagnostics.Contracts;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +30,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 
@@ -128,4 +128,5 @@
       g.AddTerminalSymbols(new string[] { "Move", "Left", "Right" });
       base.Encoding = new SymbolicExpressionTreeEncoding(g, 20, 10);
+      base.Encoding.GrammarParameter.ReadOnly = true;
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/BasicSymbolicRegression/Problem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/BasicSymbolicRegression/Problem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/BasicSymbolicRegression/Problem.cs	(revision 16892)
@@ -23,9 +23,9 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.Problems.DataAnalysis;
 using HeuristicLab.Problems.Instances;
@@ -87,4 +87,5 @@
       var g = new SimpleSymbolicExpressionGrammar(); // empty grammar is replaced in UpdateGrammar()
       base.Encoding = new SymbolicExpressionTreeEncoding(g, 100, 17);
+      Encoding.GrammarParameter.ReadOnly = true;
 
       UpdateGrammar();
@@ -177,5 +178,7 @@
       }
 
+      Encoding.GrammarParameter.ReadOnly = false;
       Encoding.Grammar = g;
+      Encoding.GrammarParameter.ReadOnly = true;
     }
     #endregion
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/Boolean/EvenParityProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/Boolean/EvenParityProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/Boolean/EvenParityProblem.cs	(revision 16892)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -28,5 +29,4 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/Boolean/MultiplexerProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/Boolean/MultiplexerProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/Boolean/MultiplexerProblem.cs	(revision 16892)
@@ -24,4 +24,5 @@
 using System.Diagnostics.Contracts;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +30,4 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 
@@ -88,4 +88,5 @@
       var g = new SimpleSymbolicExpressionGrammar(); // will be replaced in update grammar
       Encoding = new SymbolicExpressionTreeEncoding(g, 100, 17);
+      Encoding.GrammarParameter.ReadOnly = true;
 
       UpdateGrammar();
@@ -110,5 +111,7 @@
         g.AddTerminalSymbol(string.Format("d{0}", i));
 
+      Encoding.GrammarParameter.ReadOnly = false;
       Encoding.Grammar = g;
+      Encoding.GrammarParameter.ReadOnly = true;
 
       BestKnownQuality = Math.Pow(2, NumberOfBits); // this is a benchmark problem (the best achievable quality is known for a given number of bits)
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/robocode/Problem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/robocode/Problem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.GeneticProgramming/3.3/robocode/Problem.cs	(revision 16892)
@@ -20,4 +20,5 @@
 #endregion
 
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -26,5 +27,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.GeneticProgramming.Robocode {
@@ -86,4 +86,5 @@
 
       Encoding = new SymbolicExpressionTreeEncoding(new Grammar(), 1000, 10);
+      Encoding.GrammarParameter.ReadOnly = true;
       Encoding.FunctionArguments = 0;
       Encoding.FunctionDefinitions = 0;
@@ -134,5 +135,5 @@
     }
 
-    void RobocodePathParameter_ValueChanged(object sender, System.EventArgs e) {
+    private void RobocodePathParameter_ValueChanged(object sender, System.EventArgs e) {
       EnemiesParameter.Value.RobocodePath = RobocodePathParameter.Value.Value;
     }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.Programmable/3.3/Templates/CompiledMultiObjectiveProblemDefinition.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.Programmable/3.3/Templates/CompiledMultiObjectiveProblemDefinition.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.Programmable/3.3/Templates/CompiledMultiObjectiveProblemDefinition.cs	(revision 16892)
@@ -1,4 +1,16 @@
-﻿using HeuristicLab.Core;
+﻿using System;
+using System.Linq;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Encodings.LinearLinkageEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Problems.Programmable;
 
 namespace HeuristicLab.Problems.Programmable {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.Programmable/3.3/Templates/CompiledSingleObjectiveProblemDefinition.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.Programmable/3.3/Templates/CompiledSingleObjectiveProblemDefinition.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.Programmable/3.3/Templates/CompiledSingleObjectiveProblemDefinition.cs	(revision 16892)
@@ -1,5 +1,16 @@
-﻿using System.Collections.Generic;
+﻿using System;
+using System.Linq;
+using System.Collections.Generic;
+using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.BinaryVectorEncoding;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Encodings.LinearLinkageEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Optimization;
+using HeuristicLab.Problems.Programmable;
 
 namespace HeuristicLab.Problems.Programmable {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs	(revision 16892)
@@ -24,4 +24,5 @@
 using System.IO;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
@@ -32,5 +33,4 @@
 using HeuristicLab.Optimization.Operators;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 using HeuristicLab.PluginInfrastructure;
 using HeuristicLab.Problems.Instances;
@@ -210,5 +210,5 @@
       if (oldCoordinates != null) {
         Parameters.Remove(oldCoordinates);
-        Parameters.Add(new OptionalValueParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the cities.", oldCoordinates.Value, oldCoordinates.GetsCollected));
+        Parameters.Add(new OptionalValueParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the cities.", oldCoordinates.Value) { GetsCollected = oldCoordinates.GetsCollected });
       }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 16892)
@@ -175,5 +175,5 @@
     }
 
-    [Storable(Name = "operators", AllowOneWay = true)]
+    [Storable(OldName = "operators")]
     private List<IOperator> StorableOperators {
       set { Operators.AddRange(value); }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Scripting/3.3/Scripts/Templates/CSharpScriptTemplate.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Scripting/3.3/Scripts/Templates/CSharpScriptTemplate.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Scripting/3.3/Scripts/Templates/CSharpScriptTemplate.cs	(revision 16892)
@@ -6,5 +6,10 @@
 // use 'variables' to work with IEnumerable<T> extension methods on the script's variable store
 
+using System;
+using System.Linq;
+using System.Collections.Generic;
 
+using HeuristicLab.Core;
+using HeuristicLab.Common;
 //using HeuristicLab.Collections;
 //using HeuristicLab.Data;
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/ContentViewTests.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/ContentViewTests.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/ContentViewTests.cs	(revision 16892)
@@ -24,5 +24,4 @@
 using HeuristicLab.Common;
 using HeuristicLab.MainForm;
-using HeuristicLab.MainForm.WindowsForms;
 using HeuristicLab.PluginInfrastructure;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -38,4 +37,9 @@
       //get all non-generic and instantiable classes which implement IContentView
       foreach (Type viewType in ApplicationManager.Manager.GetTypes(typeof(IContentView))) {
+        // jkarder: skip this test for the SymbolicDataAnalysisModelMathView (and for views that derive from it)
+        // reason: our new build agent cannot create an instance of this view due to the use of System.Windows.Forms.WebBrowser
+        if (typeof(HeuristicLab.Problems.DataAnalysis.Symbolic.Views.SymbolicDataAnalysisModelMathView).IsAssignableFrom(viewType))
+          continue;
+
         //get all ContentAttributes on the instantiable view
         foreach (ContentAttribute attribute in viewType.GetCustomAttributes(typeof(ContentAttribute), false).Cast<ContentAttribute>()) {
@@ -48,6 +52,5 @@
         try {
           accessor.Invoke("OnContentChanged");
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
           Assert.Fail(viewType.ToString() + Environment.NewLine + ex.Message);
         }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GPSymbolicRegressionSampleWithOSTest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GPSymbolicRegressionSampleWithOSTest.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GPSymbolicRegressionSampleWithOSTest.cs	(revision 16892)
@@ -67,10 +67,10 @@
         // been able to identify the real cause. Presumably, execution on a Xeon and a Core i7 processor 
         // leads to different results. 
-        Assert.AreEqual(0.90811178793448177, SamplesUtils.GetDoubleResult(osga, "BestQuality"), 1E-8, Environment.NewLine + "Best Quality differs.");
-        Assert.AreEqual(0.87264498853305739, SamplesUtils.GetDoubleResult(osga, "CurrentAverageQuality"), 1E-8, Environment.NewLine + "Current Average Quality differs.");
-        Assert.AreEqual(0.75425658608938817, SamplesUtils.GetDoubleResult(osga, "CurrentWorstQuality"), 1E-8, Environment.NewLine + "Current Worst Quality differs.");
-        Assert.AreEqual(8900, SamplesUtils.GetIntResult(osga, "EvaluatedSolutions"), Environment.NewLine + "Evaluated Solutions differ.");
-        Assert.AreEqual(0.90811178793448177, bestTrainingSolution.TrainingRSquared, 1E-8, Environment.NewLine + "Best Training Solution Training R² differs.");
-        // Assert.AreEqual(0.896290231994223, bestTrainingSolution.TestRSquared, 1E-8, Environment.NewLine + "Best Training Solution Test R² differs.");
+        Assert.AreEqual(0.99174959007940156, SamplesUtils.GetDoubleResult(osga, "BestQuality"), 1E-8, Environment.NewLine + "Best Quality differs.");
+        Assert.AreEqual(0.9836083751914968, SamplesUtils.GetDoubleResult(osga, "CurrentAverageQuality"), 1E-8, Environment.NewLine + "Current Average Quality differs.");
+        Assert.AreEqual(0.98298394717065463, SamplesUtils.GetDoubleResult(osga, "CurrentWorstQuality"), 1E-8, Environment.NewLine + "Current Worst Quality differs.");
+        Assert.AreEqual(10100, SamplesUtils.GetIntResult(osga, "EvaluatedSolutions"), Environment.NewLine + "Evaluated Solutions differ.");
+        Assert.AreEqual(0.99174959007940156, bestTrainingSolution.TrainingRSquared, 1E-8, Environment.NewLine + "Best Training Solution Training R² differs.");
+        Assert.AreEqual(0.8962902319942232, bestTrainingSolution.TestRSquared, 1E-8, Environment.NewLine + "Best Training Solution Test R² differs.");
       } else {
         Assert.AreEqual(0.9971536312165723, SamplesUtils.GetDoubleResult(osga, "BestQuality"), 1E-8, Environment.NewLine + "Best Qualitiy differs.");
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GaussianProcessRegressionSampleTest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GaussianProcessRegressionSampleTest.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GaussianProcessRegressionSampleTest.cs	(revision 16892)
@@ -50,6 +50,6 @@
       gpr.Seed = 1618551877;
       SamplesUtils.RunAlgorithm(gpr);
-      Assert.AreEqual(-940.60591737780555, SamplesUtils.GetDoubleResult(gpr, "NegativeLogLikelihood"));
-      Assert.AreEqual(0.99560909041069334, SamplesUtils.GetDoubleResult(gpr, "Training R²"));
+      Assert.AreEqual(-940.70700288855619, SamplesUtils.GetDoubleResult(gpr, "NegativeLogLikelihood"));
+      Assert.AreEqual(0.99563390794061979, SamplesUtils.GetDoubleResult(gpr, "Training R²"));
     }
 
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/DatasetTest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/DatasetTest.cs	(revision 16892)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/DatasetTest.cs	(revision 16892)
@@ -0,0 +1,78 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Problems.DataAnalysis.Tests {
+  [TestClass]
+  public class DatasetTest {
+    private TestContext testContextInstance;
+    /// <summary>
+    ///Gets or sets the test context which provides
+    ///information about and functionality for the current test run.
+    ///</summary>
+    public TestContext TestContext {
+      get { return testContextInstance; }
+      set { testContextInstance = value; }
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis")]
+    [TestProperty("Time", "short")]
+    public void TestImportRowiseData() {
+      var matrix = new double[,] { { 1, 2, 3 }, { 2, 3, 1 }, { 3, 1, 2 }, { 1, 2, 3 }, { 2, 3, 1 } };
+      var ds = Dataset.FromRowData(new[] { "X1", "X2", "X3" }, matrix);
+      Assert.AreEqual(3, ds.Columns);
+      Assert.AreEqual(5, ds.Rows);
+      Assert.IsTrue(ds.GetDoubleValues("X1").SequenceEqual(new double[] { 1, 2, 3, 1, 2 }));
+
+      var listoflits = new List<List<double>>() {
+        new List<double>() { 1, 2, 3 },
+        new List<double>() { 2, 3, 1 },
+        new List<double>() { 3, 1, 2 },
+        new List<double>() { 1, 2, 3 },
+        new List<double>() { 2, 3, 1 }
+      };
+      ds = Dataset.FromRowData(new[] { "X1", "X2", "X3" }, listoflits);
+      Assert.AreEqual(3, ds.Columns);
+      Assert.AreEqual(5, ds.Rows);
+      Assert.IsTrue(ds.GetDoubleValues("X1").SequenceEqual(new double[] { 1, 2, 3, 1, 2 }));
+
+      var complexData = new List<IList>() {
+        new object[] { 1.0, new DateTime(2019, 1, 1), "a" },
+        new object[] { 2.0, new DateTime(2019, 1, 2), "b" },
+        new object[] { 3.0, new DateTime(2019, 1, 3), "c" },
+        new object[] { 4.0, new DateTime(2019, 1, 4), "d" },
+        new object[] { 5.0, new DateTime(2019, 1, 5), "e" },
+      };
+      ds = Dataset.FromRowData(new[] { "X1", "X2", "X3" }, complexData);
+      Assert.AreEqual(3, ds.Columns);
+      Assert.AreEqual(5, ds.Rows);
+      Assert.IsTrue(ds.GetDoubleValues("X1").SequenceEqual(new double[] { 1, 2, 3, 4, 5 }));
+      Assert.IsTrue(ds.GetDateTimeValues("X2").SequenceEqual(Enumerable.Range(1, 5).Select(d => new DateTime(2019, 1, d))));
+      Assert.IsTrue(ds.GetStringValues("X3").SequenceEqual(new string[] { "a", "b", "c", "d", "e" }));
+    }
+  }
+}
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/DeriveTest.cs	(revision 16892)
@@ -65,4 +65,8 @@
 
       Assert.AreEqual("0", Derive("(a+b)/(x+SQR(x))", "y")); // df(a,b,x) / dy = 0
+
+
+      Assert.AreEqual("('a' * 'b' * 'c')", Derive("a*b*c*d", "d"));
+      Assert.AreEqual("('a' / ('b' * 'c' * SQR('d') * (-1)))", Derive("a/b/c/d", "d")); 
 
       {
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/IntervalInterpreterTest.cs	(revision 16892)
@@ -34,5 +34,5 @@
     }
 
-    private void EvaluateTest(string expression, Interval expectedResult, Dictionary<string, Interval> variableRanges = null) {
+    private void EvaluateTest(string expression, Interval expectedResult, Dictionary<string, Interval> variableRanges = null, double lowerDelta =0, double upperDelta = 0) {
       var parser = new InfixExpressionParser();
       var tree = parser.Parse(expression);
@@ -40,9 +40,10 @@
       Interval result;
       if (variableRanges == null)
-        result = interpreter.GetSymbolicExressionTreeInterval(tree, problemData.Dataset, problemData.AllIndices);
+        result = interpreter.GetSymbolicExpressionTreeInterval(tree, problemData.Dataset, problemData.AllIndices);
       else
-        result = interpreter.GetSymbolicExressionTreeInterval(tree, variableRanges);
+        result = interpreter.GetSymbolicExpressionTreeInterval(tree, variableRanges);
 
-      Assert.AreEqual(expectedResult, result);
+      Assert.AreEqual(expectedResult.LowerBound, result.LowerBound, lowerDelta);
+      Assert.AreEqual(expectedResult.UpperBound, result.UpperBound, upperDelta);
     }
 
@@ -79,4 +80,17 @@
       EvaluateTest("sin(x1+x2)", new Interval(-1, 1), variableRanges);
       EvaluateTest("sin(1+2)", new Interval(Math.Sin(3), Math.Sin(3)));
+
+      var localVarRanges = new Dictionary<string, Interval>();
+      localVarRanges.Add("x1", new Interval(-1, 1));
+      localVarRanges.Add("x2", new Interval(-(Math.PI / 2), 0));
+      localVarRanges.Add("x3", new Interval(0, Math.PI / 2));
+      localVarRanges.Add("x4", new Interval(-Math.PI, Math.PI));
+      localVarRanges.Add("x5", new Interval(Math.PI/4, Math.PI*3.0/4));
+
+      EvaluateTest("sin(x1)", new Interval(Math.Sin(-1), Math.Sin(1)), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("sin(x2)", new Interval(-1, 0), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("sin(x3)", new Interval(0, 1), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("sin(x4)", new Interval(-1, 1), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("sin(x5)", new Interval(Math.Sin(Math.PI/4), 1), localVarRanges, 1E-8, 1E-8);
     }
 
@@ -87,6 +101,57 @@
       EvaluateTest("cos(x1+x2)", new Interval(-1, 1));
       EvaluateTest("cos(x1+x2)", new Interval(-1, 1), variableRanges);
-      EvaluateTest("cos(1+2)", new Interval(Math.Sin(3 - Math.PI / 2), Math.Sin(3 - Math.PI / 2)));
+      EvaluateTest("cos(1+2)", new Interval(Math.Sin(3 + Math.PI / 2), Math.Sin(3 + Math.PI / 2)));
+
+      var localVarRanges = new Dictionary<string, Interval>();
+      localVarRanges.Add("x1", new Interval(-1, 1));
+      localVarRanges.Add("x2", new Interval(-(Math.PI / 2), 0));
+      localVarRanges.Add("x3", new Interval(0, Math.PI / 2));
+      localVarRanges.Add("x4", new Interval(-Math.PI, Math.PI));
+      localVarRanges.Add("x5", new Interval(Math.PI / 4, Math.PI * 3.0 / 4));
+
+      EvaluateTest("cos(x1)", new Interval(Math.Cos(-1), 1), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("cos(x2)", new Interval(0, 1), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("cos(x3)", new Interval(0, 1), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("cos(x4)", new Interval(-1, 1), localVarRanges, 1E-8, 1E-8);
+      EvaluateTest("cos(x5)", new Interval(Math.Cos(Math.PI *3.0/ 4), Math.Cos(Math.PI/ 4)), localVarRanges, 1E-8, 1E-8);
+
     }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterTan() {
+      // critical values:
+      // lim tan(x) = -inf for x => -pi/2
+      // lim tan(x) = +inf for x =>  pi/2
+      var variableRanges = new Dictionary<string, Interval>();
+      variableRanges.Add("x1", new Interval(-1, 1));
+      variableRanges.Add("x2", new Interval(-(Math.PI / 2), 0));
+      variableRanges.Add("x3", new Interval(0, Math.PI / 2));
+      variableRanges.Add("x4", new Interval(-Math.PI, Math.PI));
+
+      EvaluateTest("tan(x1)", new Interval(Math.Tan(-1), Math.Tan(1)), variableRanges, 1E-8, 1E-8);
+      EvaluateTest("tan(x2)", new Interval(double.NegativeInfinity, 0), variableRanges, 0, 1E-8);
+      EvaluateTest("tan(x3)", new Interval(0, 8.16588936419192E+15), variableRanges, 0, 1E6); // actually upper bound should be infinity.
+      EvaluateTest("tan(x4)", new Interval(double.NegativeInfinity, double.PositiveInfinity), variableRanges);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void TestIntervalInterpreterTanh() {
+      // critical values:
+      // lim tanh(x) = -1 for x => -inf
+      // lim tanh(x) =  1 for x =>  inf
+      var variableRanges = new Dictionary<string, Interval>();
+      variableRanges.Add("x1", new Interval(-1, 1));
+      variableRanges.Add("x2", new Interval(double.NegativeInfinity, 0));
+      variableRanges.Add("x3", new Interval(0, double.PositiveInfinity));
+
+      EvaluateTest("tanh(x1)", new Interval(Math.Tanh(-1), Math.Tanh(1)), variableRanges);
+      EvaluateTest("tanh(x2)", new Interval(-1, 0), variableRanges);
+      EvaluateTest("tanh(x3)", new Interval(0, 1), variableRanges);
+    }
+
 
     [TestMethod]
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionTreeBottomUpSimilarityCalculatorTest.cs
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionTreeBottomUpSimilarityCalculatorTest.cs	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionTreeBottomUpSimilarityCalculatorTest.cs	(revision 16892)
@@ -7,8 +7,8 @@
   [TestClass]
   public class BottomUpSimilarityCalculatorTest {
-    private readonly SymbolicExpressionTreeBottomUpSimilarityCalculator similarityCalculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator() { MatchConstantValues = false, MatchVariableWeights = false };
     private readonly SymbolicExpressionImporter importer = new SymbolicExpressionImporter();
+    private readonly InfixExpressionParser parser = new InfixExpressionParser();
 
-    private const int N = 1000;
+    private const int N = 200;
     private const int Rows = 1;
     private const int Columns = 10;
@@ -22,24 +22,48 @@
     [TestProperty("Time", "short")]
     public void BottomUpTreeSimilarityCalculatorTestMapping() {
-      TestMatchedNodes("(+ 1 1)", "(+ 2 2)", 0, strict: true);
-      TestMatchedNodes("(+ 1 1)", "(+ 2 2)", 3, strict: false);
-      TestMatchedNodes("(+ 1 1)", "(+ 1 2)", 1, strict: true);
-      TestMatchedNodes("(+ 2 1)", "(+ 1 2)", 3, strict: true);
+      TestMatchedNodes("1 + 1", "2 + 2", 0, strict: true);
+      TestMatchedNodes("1 + 1", "2 + 2", 3, strict: false);
+      TestMatchedNodes("1 + 1", "1 + 2", 1, strict: true);
+      TestMatchedNodes("1 + 2", "2 + 1", 3, strict: true);
 
-      TestMatchedNodes("(- 1 1)", "(- 2 2)", 0, strict: true);
-      TestMatchedNodes("(- 1 1)", "(- 2 2)", 3, strict: false);
+      TestMatchedNodes("1 - 1", "2 - 2", 0, strict: true);
+      TestMatchedNodes("1 - 1", "2 - 2", 4, strict: false); // 4, because of the way strings are parsed into trees by the infix parser
 
-      TestMatchedNodes("(- 2 1)", "(- 1 2)", 2, strict: true);
-      TestMatchedNodes("(- 2 1)", "(- 1 2)", 3, strict: false);
+      TestMatchedNodes("2 - 1", "1 - 2", 2, strict: true);
+      TestMatchedNodes("2 - 1", "1 - 2", 4, strict: false);
+
+      TestMatchedNodes("(X1 * X2) + (X3 * X4)", "(X1 * X2) + (X3 * X4)", 7, strict: true);
+      TestMatchedNodes("(X1 * X2) + (X3 * X4)", "(X1 * X2) + (X3 * X4)", 7, strict: false);
+
+      TestMatchedNodes("(X1 * X2) + (X3 * X4)", "(X1 * X2) + (X5 * X6)", 3, strict: true);
+      TestMatchedNodes("(X1 * X2) + (X3 * X4)", "(X1 * X2) + (X5 * X6)", 3, strict: false);
+
+      TestMatchedNodes("(X1 * X2) + (X3 * X4)", "(X1 * X2) - (X5 * X6)", 3, strict: true);
+      TestMatchedNodes("(X1 * X2) + (X3 * X4)", "(X1 * X2) - (X5 * X6)", 3, strict: false);
+
+      TestMatchedNodes("SIN(SIN(SIN(X1)))", "SIN(SIN(SIN(X1)))", 4, strict: true);
+      TestMatchedNodes("SIN(SIN(SIN(X1)))", "COS(SIN(SIN(X1)))", 3, strict: true);
+      TestMatchedNodes("SIN(SIN(SIN(X1)))", "COS(COS(SIN(X1)))", 2, strict: true);
+      TestMatchedNodes("SIN(SIN(SIN(X1)))", "COS(COS(COS(X1)))", 1, strict: true);
+
+      const string lhs = "(0.006153 + (X9 * X7 * X2 * 0.229506) + (X6 * X10 * X3 * 0.924598) + (X2 * X1 * 0.951272) + (X4 * X3 * 0.992570) + (X6 * X5 * 1.027299))";
+      const string rhs = "(0.006153 + (X10 * X7 * X2 * 0.229506) + (X6 * X10 * X3 * 0.924598) + (X2 * X1 * 0.951272) + (X4 * X3 * 0.992570) + (X6 * X5 * 1.027299))";
+
+      TestMatchedNodes(lhs, lhs, 24, strict: true);
+      TestMatchedNodes(lhs, lhs, 24, strict: false);
+
+      TestMatchedNodes(lhs, rhs, 21, strict: true);
+      TestMatchedNodes(lhs, rhs, 21, strict: false);
     }
 
     private void TestMatchedNodes(string expr1, string expr2, int expected, bool strict) {
-      var t1 = importer.Import(expr1);
-      var t2 = importer.Import(expr2);
+      var t1 = parser.Parse(expr1);
+      var t2 = parser.Parse(expr2);
 
       var map = SymbolicExpressionTreeBottomUpSimilarityCalculator.ComputeBottomUpMapping(t1, t2, strict);
+      Console.WriteLine($"Count: {map.Count}");
 
       if (map.Count != expected) {
-        throw new Exception($"Match count {map.Count} is different than expected value {expected} for expressions:\n{expr1} and {expr2} (strict = {strict})");
+        throw new Exception($"Match count {map.Count} is different than expected value {expected} for expressions:\n{expr1} and {expr2} (strict = {strict})\n");
       }
     }
@@ -58,4 +82,6 @@
       var sw = new Stopwatch();
 
+      var similarityCalculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator { MatchVariableWeights = false, MatchConstantValues = false };
+
       sw.Start();
       for (int i = 0; i < trees.Length - 1; ++i) {
@@ -69,4 +95,41 @@
       Console.WriteLine(N * (N + 1) / (2 * sw.ElapsedMilliseconds / 1000.0) + " similarity calculations per second.");
     }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void BottomUpTreeSimilarityCalculatorStrictMatchingConsistency() {
+      TestMatchingConsistency(strict: true);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void BottomUpTreeSimilarityCalculatorRelaxedMatchingConsistency() {
+      TestMatchingConsistency(strict: false);
+    }
+
+    private static void TestMatchingConsistency(bool strict = false) {
+      var grammar = new TypeCoherentExpressionGrammar();
+      grammar.ConfigureAsDefaultRegressionGrammar();
+      var twister = new MersenneTwister(31415);
+      var ds = Util.CreateRandomDataset(twister, Rows, Columns);
+      var trees = Util.CreateRandomTrees(twister, ds, grammar, N, 1, 100, 0, 0);
+
+      var similarityCalculator = new SymbolicExpressionTreeBottomUpSimilarityCalculator { MatchConstantValues = strict, MatchVariableWeights = strict };
+      var bottomUpSimilarity = 0d;
+      for (int i = 0; i < trees.Length - 1; ++i) {
+        for (int j = i + 1; j < trees.Length; ++j) {
+          bottomUpSimilarity += similarityCalculator.CalculateSimilarity(trees[i], trees[j]);
+        }
+      }
+      bottomUpSimilarity /= N * (N - 1) / 2;
+
+      var hashBasedSimilarity = SymbolicExpressionTreeHash.ComputeAverageSimilarity(trees, false, strict);
+
+      Assert.AreEqual(bottomUpSimilarity, hashBasedSimilarity, 1e-6);
+
+      Console.WriteLine($"Bottom-up similarity: {bottomUpSimilarity}, hash-based similarity: {hashBasedSimilarity}");
+    }
   }
 }
Index: /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16891)
+++ /branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 16892)
@@ -295,4 +295,9 @@
     <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis-3.4">
       <HintPath>..\bin\HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis-3.4.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic.Views-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\bin\HeuristicLab.Problems.DataAnalysis.Symbolic.Views-3.4.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -586,4 +591,5 @@
     <Compile Include="HeuristicLab.PluginInfraStructure-3.3\TypeExtensionsTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\ClassificationVariableImpactCalculationTest.cs" />
+    <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\DatasetTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\IntervalTest.cs" />
     <Compile Include="HeuristicLab.Problems.DataAnalysis-3.4\RegressionVariableImpactCalculationTest.cs" />
