Index: /trunk/HeuristicLab 3.3.sln
===================================================================
--- /trunk/HeuristicLab 3.3.sln	(revision 17078)
+++ /trunk/HeuristicLab 3.3.sln	(revision 17079)
@@ -470,4 +470,6 @@
 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.Algorithms.DataAnalysis.DecisionTrees-3.4", "HeuristicLab.Algorithms.DataAnalysis.DecisionTrees\3.4\HeuristicLab.Algorithms.DataAnalysis.DecisionTrees-3.4.csproj", "{541A53F3-E6A7-402F-91BB-D76041CDD9FD}"
 EndProject
 Global
@@ -2293,4 +2295,16 @@
 		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|x86.ActiveCfg = Release|Any CPU
 		{CCC5D1F9-0551-4BF3-8898-E4C44B52E5A6}.Release|x86.Build.0 = Release|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Debug|x64.Build.0 = Debug|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Debug|x86.Build.0 = Debug|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Release|x64.ActiveCfg = Release|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Release|x64.Build.0 = Release|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Release|x86.ActiveCfg = Release|Any CPU
+		{541A53F3-E6A7-402F-91BB-D76041CDD9FD}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/DecisionTreeRegression.cs
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/DecisionTreeRegression.cs	(revision 17079)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/DecisionTreeRegression.cs	(revision 17079)
@@ -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: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees-3.4.csproj
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees-3.4.csproj	(revision 17079)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees-3.4.csproj	(revision 17079)
@@ -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>{541A53F3-E6A7-402F-91BB-D76041CDD9FD}</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="DecisionTreeRegression.cs" />
+    <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="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" />
+    <Compile Include="Utilities\PrincipleComponentTransformation.cs" />
+    <Compile Include="Utilities\RegressionTreeAnalyzer.cs" />
+    <Compile Include="Utilities\RegressionTreeParameters.cs" />
+    <Compile Include="Utilities\RegressionTreeUtilities.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: unk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/HeuristicLab.Algorithms.DataAnalysis.M5-3.4.csproj
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/HeuristicLab.Algorithms.DataAnalysis.M5-3.4.csproj	(revision 17078)
+++ 	(revision )
@@ -1,213 +1,0 @@
-﻿<?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: unk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/M5Regression.cs
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/M5Regression.cs	(revision 17078)
+++ 	(revision )
@@ -1,306 +1,0 @@
-#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: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Plugin.cs.frame
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Plugin.cs.frame	(revision 17078)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Plugin.cs.frame	(revision 17079)
@@ -24,8 +24,8 @@
 namespace HeuristicLab.Algorithms.DataAnalysis {
   /// <summary>
-  /// Plugin class for HeuristicLab.Algorithms.DataAnalysis plugin.
+  /// Plugin class.
   /// </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)]
+  [Plugin("HeuristicLab.Algorithms.DataAnalysis.DecisionTrees", "Provides algorithms for decision trees for regression", "3.4.0.$WCREV$")]
+  [PluginFile("HeuristicLab.Algorithms.DataAnalysis.DecisionTrees-3.4.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.ALGLIB", "3.7")]
   [PluginDependency("HeuristicLab.Attic", "1.0")]
Index: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/PrincipleComponentTransformation.cs
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/PrincipleComponentTransformation.cs	(revision 17079)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/PrincipleComponentTransformation.cs	(revision 17079)
@@ -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: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeAnalyzer.cs
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeAnalyzer.cs	(revision 17079)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeAnalyzer.cs	(revision 17079)
@@ -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: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeParameters.cs
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeParameters.cs	(revision 17079)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeParameters.cs	(revision 17079)
@@ -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: /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeUtilities.cs
===================================================================
--- /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeUtilities.cs	(revision 17079)
+++ /trunk/HeuristicLab.Algorithms.DataAnalysis.DecisionTrees/3.4/Utilities/RegressionTreeUtilities.cs	(revision 17079)
@@ -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()));
+    }
+  }
+}
