Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Dataset.cs	(revision 7570)
@@ -0,0 +1,247 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Collections.ObjectModel;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [Item("Dataset", "Represents a dataset containing data that should be analyzed.")]
+  [StorableClass]
+  public sealed class Dataset : NamedItem, IStringConvertibleMatrix {
+    [StorableConstructor]
+    private Dataset(bool deserializing) : base(deserializing) { }
+    private Dataset(Dataset original, Cloner cloner)
+      : base(original, cloner) {
+      variableValues = new Dictionary<string, IList>(original.variableValues);
+      variableNames = new List<string>(original.variableNames);
+      rows = original.rows;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new Dataset(this, cloner); }
+
+    public Dataset()
+      : base() {
+      Name = "-";
+      VariableNames = Enumerable.Empty<string>();
+      variableValues = new Dictionary<string, IList>();
+      rows = 0;
+    }
+
+    public Dataset(IEnumerable<string> variableNames, IEnumerable<IList> variableValues)
+      : base() {
+      Name = "-";
+      if (!variableNames.Any()) {
+        this.variableNames = Enumerable.Range(0, variableValues.Count()).Select(x => "Column " + x).ToList();
+      } else if (variableNames.Count() != variableValues.Count()) {
+        throw new ArgumentException("Number of variable names doesn't match the number of columns of variableValues");
+      } else if (!variableValues.All(list => list.Count == variableValues.First().Count)) {
+        throw new ArgumentException("The number of values must be equal for every variable");
+      } else if (variableNames.Distinct().Count() != variableNames.Count()) {
+        var duplicateVariableNames =
+          variableNames.GroupBy(v => v).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
+        string message = "The dataset cannot contain duplicate variables names: " + Environment.NewLine;
+        foreach (var duplicateVariableName in duplicateVariableNames)
+          message += duplicateVariableName + Environment.NewLine;
+        throw new ArgumentException(message);
+      }
+
+      rows = variableValues.First().Count;
+      this.variableNames = new List<string>(variableNames);
+      this.variableValues = new Dictionary<string, IList>();
+      for (int i = 0; i < this.variableNames.Count; i++) {
+        var values = variableValues.ElementAt(i);
+        IList clonedValues = null;
+        if (values is List<double>)
+          clonedValues = new List<double>(values.Cast<double>());
+        else if (values is List<string>)
+          clonedValues = new List<string>(values.Cast<string>());
+        else if (values is List<DateTime>)
+          clonedValues = new List<DateTime>(values.Cast<DateTime>());
+        else {
+          this.variableNames = new List<string>();
+          this.variableValues = new Dictionary<string, IList>();
+          throw new ArgumentException("The variable values must be of type List<double>, List<string> or List<DateTime>");
+        }
+        this.variableValues.Add(this.variableNames[i], clonedValues);
+      }
+    }
+
+    public Dataset(IEnumerable<string> variableNames, double[,] variableValues) {
+      Name = "-";
+      if (variableNames.Count() != variableValues.GetLength(1)) {
+        throw new ArgumentException("Number of variable names doesn't match the number of columns of variableValues");
+      }
+      if (variableNames.Distinct().Count() != variableNames.Count()) {
+        var duplicateVariableNames = variableNames.GroupBy(v => v).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
+        string message = "The dataset cannot contain duplicate variables names: " + Environment.NewLine;
+        foreach (var duplicateVariableName in duplicateVariableNames)
+          message += duplicateVariableName + Environment.NewLine;
+        throw new ArgumentException(message);
+      }
+
+      rows = variableValues.GetLength(0);
+      this.variableNames = new List<string>(variableNames);
+
+      this.variableValues = new Dictionary<string, IList>();
+      for (int col = 0; col < variableValues.GetLength(1); col++) {
+        string columName = this.variableNames[col];
+        var values = new List<double>();
+        for (int row = 0; row < variableValues.GetLength(0); row++) {
+          values.Add(variableValues[row, col]);
+        }
+        this.variableValues.Add(columName, values);
+      }
+    }
+
+    #region Backwards compatible code, remove with 3.5
+    private double[,] storableData;
+    //name alias used to suppport backwards compatibility
+    [Storable(Name = "data", AllowOneWay = true)]
+    private double[,] StorableData { set { storableData = value; } }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (variableValues == null) {
+        rows = storableData.GetLength(0);
+        variableValues = new Dictionary<string, IList>();
+        for (int col = 0; col < storableData.GetLength(1); col++) {
+          string columName = variableNames[col];
+          var values = new List<double>();
+          for (int row = 0; row < storableData.GetLength(0); row++) {
+            values.Add(storableData[row, col]);
+          }
+          variableValues.Add(columName, values);
+        }
+        storableData = null;
+      }
+    }
+    #endregion
+
+    [Storable(Name = "VariableValues")]
+    private Dictionary<string, IList> variableValues;
+
+    private List<string> variableNames;
+    [Storable]
+    public IEnumerable<string> VariableNames {
+      get { return variableNames; }
+      private set {
+        if (variableNames != null) throw new InvalidOperationException();
+        variableNames = new List<string>(value);
+      }
+    }
+
+    public IEnumerable<string> DoubleVariables {
+      get { return variableValues.Where(p => p.Value is List<double>).Select(p => p.Key); }
+    }
+
+    public IEnumerable<double> GetDoubleValues(string variableName) {
+      IList list;
+      if (!variableValues.TryGetValue(variableName, out list))
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      List<double> values = list as List<double>;
+      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
+
+      //mkommend yield return used to enable lazy evaluation
+      foreach (double value in values)
+        yield return value;
+    }
+    public ReadOnlyCollection<double> GetReadOnlyDoubleValues(string variableName) {
+      IList list;
+      if (!variableValues.TryGetValue(variableName, out list))
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      List<double> values = list as List<double>;
+      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
+      return values.AsReadOnly();
+    }
+    public double GetDoubleValue(string variableName, int row) {
+      IList list;
+      if (!variableValues.TryGetValue(variableName, out list))
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      List<double> values = list as List<double>;
+      if (values == null) throw new ArgumentException("The variable " + variableName + " is not a double variable.");
+      return values[row];
+    }
+    public IEnumerable<double> GetDoubleValues(string variableName, IEnumerable<int> rows) {
+      IList list;
+      if (!variableValues.TryGetValue(variableName, out list))
+        throw new ArgumentException("The variable " + variableName + " does not exist in the dataset.");
+      List<double> values = list as List<double>;
+      if (values == null) throw new ArgumentException("The varialbe " + variableName + " is not a double variable.");
+
+      foreach (int index in rows)
+        yield return values[index];
+    }
+
+    #region IStringConvertibleMatrix Members
+    [Storable]
+    private int rows;
+    public int Rows {
+      get { return rows; }
+      set { throw new NotSupportedException(); }
+    }
+    public int Columns {
+      get { return variableNames.Count; }
+      set { throw new NotSupportedException(); }
+    }
+
+    public bool SortableView {
+      get { return false; }
+      set { throw new NotSupportedException(); }
+    }
+    public bool ReadOnly {
+      get { return true; }
+    }
+
+    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
+      get { return this.VariableNames; }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.RowNames {
+      get { return Enumerable.Empty<string>(); }
+      set { throw new NotSupportedException(); }
+    }
+
+    public string GetValue(int rowIndex, int columnIndex) {
+      return variableValues[variableNames[columnIndex]][rowIndex].ToString();
+    }
+    public bool SetValue(string value, int rowIndex, int columnIndex) {
+      throw new NotSupportedException();
+    }
+    public bool Validate(string value, out string errorMessage) {
+      throw new NotSupportedException();
+    }
+
+    public event EventHandler ColumnsChanged { add { } remove { } }
+    public event EventHandler RowsChanged { add { } remove { } }
+    public event EventHandler ColumnNamesChanged { add { } remove { } }
+    public event EventHandler RowNamesChanged { add { } remove { } }
+    public event EventHandler SortableViewChanged { add { } remove { } }
+    public event EventHandler<EventArgs<int, int>> ItemChanged { add { } remove { } }
+    public event EventHandler Reset { add { } remove { } }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/DoubleLimit.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/DoubleLimit.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/DoubleLimit.cs	(revision 7570)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("DoubleLimit", "Represents a lower and a upper bound for double values.")]
+  public class DoubleLimit : StringConvertibleValueTuple<DoubleValue, DoubleValue> {
+
+    public double Lower {
+      get { return Item1.Value; }
+      set { Item1.Value = value; }
+    }
+    public double Upper {
+      get { return Item2.Value; }
+      set { Item2.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected DoubleLimit(bool deserializing) : base(deserializing) { }
+    protected DoubleLimit(DoubleLimit original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DoubleLimit(this, cloner);
+    }
+
+    public DoubleLimit() : base(new DoubleValue(), new DoubleValue()) { }
+    public DoubleLimit(DoubleValue start, DoubleValue end) : base(start, end) { }
+    public DoubleLimit(double start, double end) : base(new DoubleValue(start), new DoubleValue(end)) { }
+
+    public override string ToString() {
+      return string.Format("Lower: {0}, Upper: {1}", Lower, Upper);
+    }
+
+    public override StringConvertibleValueTuple<DoubleValue, DoubleValue> AsReadOnly() {
+      var readOnly = new DoubleLimit();
+      readOnly.values = Tuple.Create<DoubleValue, DoubleValue>((DoubleValue)Item1.AsReadOnly(), (DoubleValue)Item2.AsReadOnly());
+      readOnly.readOnly = true;
+      return readOnly;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 7570)
@@ -0,0 +1,274 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{DF87C13E-A889-46FF-8153-66DCAA8C5674}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.DataAnalysis</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.DataAnalysis-3.4</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </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>
+  </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>
+  </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>AllRules.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>AllRules.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>AllRules.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>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DoubleLimit.cs" />
+    <Compile Include="Implementation\Classification\ClassificationEnsembleModel.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Implementation\Classification\ClassificationEnsembleSolution.cs" />
+    <Compile Include="Implementation\Classification\ClassificationProblemData.cs" />
+    <Compile Include="Implementation\Classification\ClassificationProblem.cs" />
+    <Compile Include="Implementation\Classification\ClassificationSolution.cs" />
+    <Compile Include="Implementation\Classification\ClassificationEnsembleProblemData.cs" />
+    <Compile Include="Implementation\Classification\ClassificationSolutionBase.cs" />
+    <Compile Include="Implementation\Classification\DiscriminantFunctionClassificationSolutionBase.cs" />
+    <Compile Include="Implementation\Clustering\ClusteringProblem.cs" />
+    <Compile Include="Implementation\Clustering\ClusteringProblemData.cs" />
+    <Compile Include="Implementation\Clustering\ClusteringSolution.cs" />
+    <Compile Include="Implementation\Regression\ConstantRegressionModel.cs" />
+    <Compile Include="Implementation\Regression\ConstantRegressionSolution.cs" />
+    <Compile Include="Implementation\Regression\RegressionEnsembleProblemData.cs" />
+    <Compile Include="Implementation\Regression\RegressionEnsembleModel.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Implementation\Regression\RegressionEnsembleSolution.cs" />
+    <Compile Include="Interfaces\Classification\IClassificationEnsembleModel.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Interfaces\Classification\IClassificationEnsembleSolution.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Interfaces\Classification\IDiscriminantFunctionThresholdCalculator.cs" />
+    <Compile Include="Interfaces\Regression\IRegressionEnsembleModel.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Interfaces\Regression\IRegressionEnsembleSolution.cs" />
+    <Compile Include="Implementation\Regression\RegressionSolutionBase.cs" />
+    <Compile Include="OnlineCalculators\OnlineMeanErrorCalculator.cs" />
+    <Compile Include="OnlineCalculators\NormalizedGiniCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlineMeanAbsoluteErrorCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlineLinearScalingParameterCalculator.cs" />
+    <Compile Include="Implementation\Classification\DiscriminantFunctionClassificationModel.cs" />
+    <Compile Include="Implementation\Classification\DiscriminantFunctionClassificationSolution.cs" />
+    <Compile Include="Implementation\DataAnalysisSolution.cs" />
+    <Compile Include="Interfaces\Classification\IDiscriminantFunctionClassificationModel.cs" />
+    <Compile Include="Interfaces\Classification\IDiscriminantFunctionClassificationSolution.cs" />
+    <Compile Include="Interfaces\Clustering\IClusteringModel.cs" />
+    <Compile Include="Interfaces\Clustering\IClusteringProblem.cs" />
+    <Compile Include="Interfaces\Clustering\IClusteringProblemData.cs" />
+    <Compile Include="Interfaces\Clustering\IClusteringSolution.cs" />
+    <Compile Include="OnlineCalculators\OnlineAccuracyCalculator.cs" />
+    <Compile Include="Implementation\Regression\RegressionProblemData.cs" />
+    <Compile Include="Implementation\DataAnalysisProblemData.cs" />
+    <Compile Include="Implementation\Regression\RegressionProblem.cs" />
+    <Compile Include="Implementation\DataAnalysisProblem.cs" />
+    <Compile Include="Dataset.cs" />
+    <Compile Include="Interfaces\Classification\IClassificationModel.cs" />
+    <Compile Include="Interfaces\Classification\IClassificationProblem.cs" />
+    <Compile Include="Interfaces\Classification\IClassificationProblemData.cs" />
+    <Compile Include="Interfaces\Classification\IClassificationSolution.cs" />
+    <Compile Include="Interfaces\IDataAnalysisProblemData.cs" />
+    <Compile Include="Interfaces\IDataAnalysisSolution.cs" />
+    <Compile Include="Interfaces\IOnlineCalculator.cs" />
+    <Compile Include="Interfaces\Regression\IRegressionModel.cs" />
+    <Compile Include="Interfaces\Regression\IRegressionProblem.cs" />
+    <Compile Include="Interfaces\Regression\IRegressionProblemData.cs" />
+    <Compile Include="Interfaces\Regression\IRegressionSolution.cs" />
+    <Compile Include="OnlineCalculators\OnlineCovarianceCalcualtor.cs" />
+    <Compile Include="OnlineCalculators\OnlineMeanAbsolutePercentageErrorCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlineMeanAndVarianceCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlineMeanSquaredErrorCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlineNormalizedMeanSquaredErrorCalculator.cs" />
+    <Compile Include="OnlineCalculators\OnlinePearsonsRSquaredCalculator.cs" />
+    <Compile Include="Implementation\Regression\RegressionSolution.cs" />
+    <Compile Include="Plugin.cs" />
+    <Compile Include="TableFileParser.cs" />
+    <Compile Include="Implementation\Classification\ThresholdCalculators\AccuracyMaximizationThresholdCalculator.cs" />
+    <Compile Include="Implementation\Classification\ThresholdCalculators\NormalDistributionCutPointsThresholdCalculator.cs" />
+    <Compile Include="Implementation\Classification\ThresholdCalculators\ThresholdCalculator.cs" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+    <Compile Include="Interfaces\IDataAnalysisModel.cs" />
+    <Compile Include="Interfaces\IDataAnalysisProblem.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <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.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-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.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.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
+      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
+      <Name>HeuristicLab.Persistence-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>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </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>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleModel.cs	(revision 7570)
@@ -0,0 +1,101 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents classification solutions that contain an ensemble of multiple classification models
+  /// </summary>
+  [StorableClass]
+  [Item("ClassificationEnsembleModel", "A classification model that contains an ensemble of multiple classification models")]
+  public class ClassificationEnsembleModel : NamedItem, IClassificationEnsembleModel {
+
+    [Storable]
+    private List<IClassificationModel> models;
+    public IEnumerable<IClassificationModel> Models {
+      get { return new List<IClassificationModel>(models); }
+    }
+
+    [StorableConstructor]
+    protected ClassificationEnsembleModel(bool deserializing) : base(deserializing) { }
+    protected ClassificationEnsembleModel(ClassificationEnsembleModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.models = original.Models.Select(m => cloner.Clone(m)).ToList();
+    }
+
+    public ClassificationEnsembleModel() : this(Enumerable.Empty<IClassificationModel>()) { }
+    public ClassificationEnsembleModel(IEnumerable<IClassificationModel> models)
+      : base() {
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.models = new List<IClassificationModel>(models);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ClassificationEnsembleModel(this, cloner);
+    }
+
+    #region IClassificationEnsembleModel Members
+    public void Add(IClassificationModel model) {
+      models.Add(model);
+    }
+    public void Remove(IClassificationModel model) {
+      models.Remove(model);
+    }
+
+    public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows) {
+      var estimatedValuesEnumerators = (from model in models
+                                        select model.GetEstimatedClassValues(dataset, rows).GetEnumerator())
+                                       .ToList();
+
+      while (estimatedValuesEnumerators.All(en => en.MoveNext())) {
+        yield return from enumerator in estimatedValuesEnumerators
+                     select enumerator.Current;
+      }
+    }
+
+    #endregion
+
+    #region IClassificationModel Members
+
+    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+      foreach (var estimatedValuesVector in GetEstimatedClassValueVectors(dataset, rows)) {
+        // return the class which is most often occuring
+        yield return
+          estimatedValuesVector
+          .GroupBy(x => x)
+          .OrderBy(g => -g.Count())
+          .Select(g => g.Key)
+          .First();
+      }
+    }
+
+    IClassificationSolution IClassificationModel.CreateClassificationSolution(IClassificationProblemData problemData) {
+      return new ClassificationEnsembleSolution(models, problemData);
+    }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleProblemData.cs	(revision 7570)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("ClassificationEnsembleProblemData", "Represents an item containing all data defining a classification problem.")]
+  public class ClassificationEnsembleProblemData : ClassificationProblemData {
+
+    public override bool IsTrainingSample(int index) {
+      return index >= 0 && index < Dataset.Rows &&
+             TrainingPartition.Start <= index && index < TrainingPartition.End;
+    }
+
+    public override bool IsTestSample(int index) {
+      return index >= 0 && index < Dataset.Rows &&
+             TestPartition.Start <= index && index < TestPartition.End;
+    }
+
+    private static readonly ClassificationEnsembleProblemData emptyProblemData;
+    public static new ClassificationEnsembleProblemData EmptyProblemData {
+      get { return emptyProblemData; }
+    }
+
+    static ClassificationEnsembleProblemData() {
+      var problemData = new ClassificationEnsembleProblemData();
+      problemData.Parameters.Clear();
+      problemData.Name = "Empty Classification ProblemData";
+      problemData.Description = "This ProblemData acts as place holder before the correct problem data is loaded.";
+      problemData.isEmpty = true;
+
+      problemData.Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", new Dataset()));
+      problemData.Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>(InputVariablesParameterName, ""));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TrainingPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TestPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>()));
+      problemData.Parameters.Add(new FixedValueParameter<StringMatrix>(ClassNamesParameterName, "", new StringMatrix(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new FixedValueParameter<DoubleMatrix>(ClassificationPenaltiesParameterName, "", (DoubleMatrix)new DoubleMatrix(0, 0).AsReadOnly()));
+      emptyProblemData = problemData;
+    }
+
+    [StorableConstructor]
+    protected ClassificationEnsembleProblemData(bool deserializing) : base(deserializing) { }
+    protected ClassificationEnsembleProblemData(ClassificationEnsembleProblemData original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      if (this == emptyProblemData) return emptyProblemData;
+      return new ClassificationEnsembleProblemData(this, cloner);
+    }
+
+    public ClassificationEnsembleProblemData() : base() { }
+    public ClassificationEnsembleProblemData(IClassificationProblemData classificationProblemData)
+      : base(classificationProblemData.Dataset, classificationProblemData.AllowedInputVariables, classificationProblemData.TargetVariable) {
+      this.TrainingPartition.Start = classificationProblemData.TrainingPartition.Start;
+      this.TrainingPartition.End = classificationProblemData.TrainingPartition.End;
+      this.TestPartition.Start = classificationProblemData.TestPartition.Start;
+      this.TestPartition.End = classificationProblemData.TestPartition.End;
+    }
+
+    public ClassificationEnsembleProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable)
+      : base(dataset, allowedInputVariables, targetVariable) {
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationEnsembleSolution.cs	(revision 7570)
@@ -0,0 +1,286 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents classification solutions that contain an ensemble of multiple classification models
+  /// </summary>
+  [StorableClass]
+  [Item("Classification Ensemble Solution", "A classification solution that contains an ensemble of multiple classification models")]
+  [Creatable("Data Analysis - Ensembles")]
+  public sealed class ClassificationEnsembleSolution : ClassificationSolution, IClassificationEnsembleSolution {
+    public new IClassificationEnsembleModel Model {
+      get { return (IClassificationEnsembleModel)base.Model; }
+    }
+    public new ClassificationEnsembleProblemData ProblemData {
+      get { return (ClassificationEnsembleProblemData)base.ProblemData; }
+      set { base.ProblemData = value; }
+    }
+
+    private readonly ItemCollection<IClassificationSolution> classificationSolutions;
+    public IItemCollection<IClassificationSolution> ClassificationSolutions {
+      get { return classificationSolutions; }
+    }
+
+    [Storable]
+    private Dictionary<IClassificationModel, IntRange> trainingPartitions;
+    [Storable]
+    private Dictionary<IClassificationModel, IntRange> testPartitions;
+
+    [StorableConstructor]
+    private ClassificationEnsembleSolution(bool deserializing)
+      : base(deserializing) {
+      classificationSolutions = new ItemCollection<IClassificationSolution>();
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      foreach (var model in Model.Models) {
+        IClassificationProblemData problemData = (IClassificationProblemData)ProblemData.Clone();
+        problemData.TrainingPartition.Start = trainingPartitions[model].Start;
+        problemData.TrainingPartition.End = trainingPartitions[model].End;
+        problemData.TestPartition.Start = testPartitions[model].Start;
+        problemData.TestPartition.End = testPartitions[model].End;
+
+        classificationSolutions.Add(model.CreateClassificationSolution(problemData));
+      }
+      RegisterClassificationSolutionsEventHandler();
+    }
+
+    private ClassificationEnsembleSolution(ClassificationEnsembleSolution original, Cloner cloner)
+      : base(original, cloner) {
+      trainingPartitions = new Dictionary<IClassificationModel, IntRange>();
+      testPartitions = new Dictionary<IClassificationModel, IntRange>();
+      foreach (var pair in original.trainingPartitions) {
+        trainingPartitions[cloner.Clone(pair.Key)] = cloner.Clone(pair.Value);
+      }
+      foreach (var pair in original.testPartitions) {
+        testPartitions[cloner.Clone(pair.Key)] = cloner.Clone(pair.Value);
+      }
+
+      classificationSolutions = cloner.Clone(original.classificationSolutions);
+      RegisterClassificationSolutionsEventHandler();
+    }
+
+    public ClassificationEnsembleSolution()
+      : base(new ClassificationEnsembleModel(), ClassificationEnsembleProblemData.EmptyProblemData) {
+      trainingPartitions = new Dictionary<IClassificationModel, IntRange>();
+      testPartitions = new Dictionary<IClassificationModel, IntRange>();
+      classificationSolutions = new ItemCollection<IClassificationSolution>();
+
+      RegisterClassificationSolutionsEventHandler();
+    }
+
+    public ClassificationEnsembleSolution(IEnumerable<IClassificationModel> models, IClassificationProblemData problemData)
+      : this(models, problemData,
+             models.Select(m => (IntRange)problemData.TrainingPartition.Clone()),
+             models.Select(m => (IntRange)problemData.TestPartition.Clone())
+      ) { }
+
+    public ClassificationEnsembleSolution(IEnumerable<IClassificationModel> models, IClassificationProblemData problemData, IEnumerable<IntRange> trainingPartitions, IEnumerable<IntRange> testPartitions)
+      : base(new ClassificationEnsembleModel(Enumerable.Empty<IClassificationModel>()), new ClassificationEnsembleProblemData(problemData)) {
+      this.trainingPartitions = new Dictionary<IClassificationModel, IntRange>();
+      this.testPartitions = new Dictionary<IClassificationModel, IntRange>();
+      this.classificationSolutions = new ItemCollection<IClassificationSolution>();
+
+      List<IClassificationSolution> solutions = new List<IClassificationSolution>();
+      var modelEnumerator = models.GetEnumerator();
+      var trainingPartitionEnumerator = trainingPartitions.GetEnumerator();
+      var testPartitionEnumerator = testPartitions.GetEnumerator();
+
+      while (modelEnumerator.MoveNext() & trainingPartitionEnumerator.MoveNext() & testPartitionEnumerator.MoveNext()) {
+        var p = (IClassificationProblemData)problemData.Clone();
+        p.TrainingPartition.Start = trainingPartitionEnumerator.Current.Start;
+        p.TrainingPartition.End = trainingPartitionEnumerator.Current.End;
+        p.TestPartition.Start = testPartitionEnumerator.Current.Start;
+        p.TestPartition.End = testPartitionEnumerator.Current.End;
+
+        solutions.Add(modelEnumerator.Current.CreateClassificationSolution(p));
+      }
+      if (modelEnumerator.MoveNext() | trainingPartitionEnumerator.MoveNext() | testPartitionEnumerator.MoveNext()) {
+        throw new ArgumentException();
+      }
+
+      RegisterClassificationSolutionsEventHandler();
+      classificationSolutions.AddRange(solutions);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ClassificationEnsembleSolution(this, cloner);
+    }
+    private void RegisterClassificationSolutionsEventHandler() {
+      classificationSolutions.ItemsAdded += new CollectionItemsChangedEventHandler<IClassificationSolution>(classificationSolutions_ItemsAdded);
+      classificationSolutions.ItemsRemoved += new CollectionItemsChangedEventHandler<IClassificationSolution>(classificationSolutions_ItemsRemoved);
+      classificationSolutions.CollectionReset += new CollectionItemsChangedEventHandler<IClassificationSolution>(classificationSolutions_CollectionReset);
+    }
+
+    protected override void RecalculateResults() {
+      CalculateResults();
+    }
+
+    #region Evaluation
+    public override IEnumerable<double> EstimatedTrainingClassValues {
+      get {
+        var rows = ProblemData.TrainingIndizes;
+        var estimatedValuesEnumerators = (from model in Model.Models
+                                          select new { Model = model, EstimatedValuesEnumerator = model.GetEstimatedClassValues(ProblemData.Dataset, rows).GetEnumerator() })
+                                         .ToList();
+        var rowsEnumerator = rows.GetEnumerator();
+        // aggregate to make sure that MoveNext is called for all enumerators 
+        while (rowsEnumerator.MoveNext() & estimatedValuesEnumerators.Select(en => en.EstimatedValuesEnumerator.MoveNext()).Aggregate(true, (acc, b) => acc & b)) {
+          int currentRow = rowsEnumerator.Current;
+
+          var selectedEnumerators = from pair in estimatedValuesEnumerators
+                                    where RowIsTrainingForModel(currentRow, pair.Model) && !RowIsTestForModel(currentRow, pair.Model)
+                                    select pair.EstimatedValuesEnumerator;
+          yield return AggregateEstimatedClassValues(selectedEnumerators.Select(x => x.Current));
+        }
+      }
+    }
+
+    public override IEnumerable<double> EstimatedTestClassValues {
+      get {
+        var rows = ProblemData.TestIndizes;
+        var estimatedValuesEnumerators = (from model in Model.Models
+                                          select new { Model = model, EstimatedValuesEnumerator = model.GetEstimatedClassValues(ProblemData.Dataset, rows).GetEnumerator() })
+                                         .ToList();
+        var rowsEnumerator = ProblemData.TestIndizes.GetEnumerator();
+        // aggregate to make sure that MoveNext is called for all enumerators 
+        while (rowsEnumerator.MoveNext() & estimatedValuesEnumerators.Select(en => en.EstimatedValuesEnumerator.MoveNext()).Aggregate(true, (acc, b) => acc & b)) {
+          int currentRow = rowsEnumerator.Current;
+
+          var selectedEnumerators = from pair in estimatedValuesEnumerators
+                                    where RowIsTestForModel(currentRow, pair.Model)
+                                    select pair.EstimatedValuesEnumerator;
+
+          yield return AggregateEstimatedClassValues(selectedEnumerators.Select(x => x.Current));
+        }
+      }
+    }
+
+    private bool RowIsTrainingForModel(int currentRow, IClassificationModel model) {
+      return trainingPartitions == null || !trainingPartitions.ContainsKey(model) ||
+              (trainingPartitions[model].Start <= currentRow && currentRow < trainingPartitions[model].End);
+    }
+
+    private bool RowIsTestForModel(int currentRow, IClassificationModel model) {
+      return testPartitions == null || !testPartitions.ContainsKey(model) ||
+              (testPartitions[model].Start <= currentRow && currentRow < testPartitions[model].End);
+    }
+
+    public override IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows) {
+      return from xs in GetEstimatedClassValueVectors(ProblemData.Dataset, rows)
+             select AggregateEstimatedClassValues(xs);
+    }
+
+    public IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows) {
+      if (!Model.Models.Any()) yield break;
+      var estimatedValuesEnumerators = (from model in Model.Models
+                                        select model.GetEstimatedClassValues(dataset, rows).GetEnumerator())
+                                       .ToList();
+
+      while (estimatedValuesEnumerators.All(en => en.MoveNext())) {
+        yield return from enumerator in estimatedValuesEnumerators
+                     select enumerator.Current;
+      }
+    }
+
+    private double AggregateEstimatedClassValues(IEnumerable<double> estimatedClassValues) {
+      return estimatedClassValues
+      .GroupBy(x => x)
+      .OrderBy(g => -g.Count())
+      .Select(g => g.Key)
+      .DefaultIfEmpty(double.NaN)
+      .First();
+    }
+    #endregion
+
+    protected override void OnProblemDataChanged() {
+      IClassificationProblemData problemData = new ClassificationProblemData(ProblemData.Dataset,
+                                                                     ProblemData.AllowedInputVariables,
+                                                                     ProblemData.TargetVariable);
+      problemData.TrainingPartition.Start = ProblemData.TrainingPartition.Start;
+      problemData.TrainingPartition.End = ProblemData.TrainingPartition.End;
+      problemData.TestPartition.Start = ProblemData.TestPartition.Start;
+      problemData.TestPartition.End = ProblemData.TestPartition.End;
+
+      foreach (var solution in ClassificationSolutions) {
+        if (solution is ClassificationEnsembleSolution)
+          solution.ProblemData = ProblemData;
+        else
+          solution.ProblemData = problemData;
+      }
+      foreach (var trainingPartition in trainingPartitions.Values) {
+        trainingPartition.Start = ProblemData.TrainingPartition.Start;
+        trainingPartition.End = ProblemData.TrainingPartition.End;
+      }
+      foreach (var testPartition in testPartitions.Values) {
+        testPartition.Start = ProblemData.TestPartition.Start;
+        testPartition.End = ProblemData.TestPartition.End;
+      }
+
+      base.OnProblemDataChanged();
+    }
+
+    public void AddClassificationSolutions(IEnumerable<IClassificationSolution> solutions) {
+      classificationSolutions.AddRange(solutions);
+    }
+    public void RemoveClassificationSolutions(IEnumerable<IClassificationSolution> solutions) {
+      classificationSolutions.RemoveRange(solutions);
+    }
+
+    private void classificationSolutions_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IClassificationSolution> e) {
+      foreach (var solution in e.Items) AddClassificationSolution(solution);
+      RecalculateResults();
+    }
+    private void classificationSolutions_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IClassificationSolution> e) {
+      foreach (var solution in e.Items) RemoveClassificationSolution(solution);
+      RecalculateResults();
+    }
+    private void classificationSolutions_CollectionReset(object sender, CollectionItemsChangedEventArgs<IClassificationSolution> e) {
+      foreach (var solution in e.OldItems) RemoveClassificationSolution(solution);
+      foreach (var solution in e.Items) AddClassificationSolution(solution);
+      RecalculateResults();
+    }
+
+    private void AddClassificationSolution(IClassificationSolution solution) {
+      if (Model.Models.Contains(solution.Model)) throw new ArgumentException();
+      Model.Add(solution.Model);
+      trainingPartitions[solution.Model] = solution.ProblemData.TrainingPartition;
+      testPartitions[solution.Model] = solution.ProblemData.TestPartition;
+    }
+
+    private void RemoveClassificationSolution(IClassificationSolution solution) {
+      if (!Model.Models.Contains(solution.Model)) throw new ArgumentException();
+      Model.Remove(solution.Model);
+      trainingPartitions.Remove(solution.Model);
+      testPartitions.Remove(solution.Model);
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblem.cs	(revision 7570)
@@ -0,0 +1,48 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("Classification Problem", "A general classification problem.")]
+  [Creatable("Problems")]
+  public class ClassificationProblem : DataAnalysisProblem<IClassificationProblemData>, IClassificationProblem, IStorableContent {
+    public string Filename { get; set; }
+
+    [StorableConstructor]
+    protected ClassificationProblem(bool deserializing) : base(deserializing) { }
+    protected ClassificationProblem(ClassificationProblem original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ClassificationProblem(this, cloner); }
+
+    public ClassificationProblem()
+      : base() {
+      ProblemData = new ClassificationProblemData();
+    }
+
+    public override void ImportProblemDataFromFile(string fileName) {
+      ClassificationProblemData problemData = ClassificationProblemData.ImportFromFile(fileName);
+      ProblemData = problemData;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationProblemData.cs	(revision 7570)
@@ -0,0 +1,420 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.IO;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("ClassificationProblemData", "Represents an item containing all data defining a classification problem.")]
+  public class ClassificationProblemData : DataAnalysisProblemData, IClassificationProblemData, IStorableContent {
+    protected const string TargetVariableParameterName = "TargetVariable";
+    protected const string ClassNamesParameterName = "ClassNames";
+    protected const string ClassificationPenaltiesParameterName = "ClassificationPenalties";
+    protected const int MaximumNumberOfClasses = 100;
+    protected const int InspectedRowsToDetermineTargets = 2000;
+
+    public string Filename { get; set; }
+
+    #region default data
+    private static string[] defaultVariableNames = new string[] { "sample", "clump thickness", "cell size", "cell shape", "marginal adhesion", "epithelial cell size", "bare nuclei", "chromatin", "nucleoli", "mitoses", "class" };
+    private static double[,] defaultData = new double[,]{
+     {1000025,5,1,1,1,2,1,3,1,1,2      },
+     {1002945,5,4,4,5,7,10,3,2,1,2     },
+     {1015425,3,1,1,1,2,2,3,1,1,2      },
+     {1016277,6,8,8,1,3,4,3,7,1,2      },
+     {1017023,4,1,1,3,2,1,3,1,1,2      },
+     {1017122,8,10,10,8,7,10,9,7,1,4   },
+     {1018099,1,1,1,1,2,10,3,1,1,2     },
+     {1018561,2,1,2,1,2,1,3,1,1,2      },
+     {1033078,2,1,1,1,2,1,1,1,5,2      },
+     {1033078,4,2,1,1,2,1,2,1,1,2      },
+     {1035283,1,1,1,1,1,1,3,1,1,2      },
+     {1036172,2,1,1,1,2,1,2,1,1,2      },
+     {1041801,5,3,3,3,2,3,4,4,1,4      },
+     {1043999,1,1,1,1,2,3,3,1,1,2      },
+     {1044572,8,7,5,10,7,9,5,5,4,4     },
+     {1047630,7,4,6,4,6,1,4,3,1,4      },
+     {1048672,4,1,1,1,2,1,2,1,1,2      },
+     {1049815,4,1,1,1,2,1,3,1,1,2      },
+     {1050670,10,7,7,6,4,10,4,1,2,4    },
+     {1050718,6,1,1,1,2,1,3,1,1,2      },
+     {1054590,7,3,2,10,5,10,5,4,4,4    },
+     {1054593,10,5,5,3,6,7,7,10,1,4    },
+     {1056784,3,1,1,1,2,1,2,1,1,2      },
+     {1057013,8,4,5,1,2,2,7,3,1,4      },
+     {1059552,1,1,1,1,2,1,3,1,1,2      },
+     {1065726,5,2,3,4,2,7,3,6,1,4      },
+     {1066373,3,2,1,1,1,1,2,1,1,2      },
+     {1066979,5,1,1,1,2,1,2,1,1,2      },
+     {1067444,2,1,1,1,2,1,2,1,1,2      },
+     {1070935,1,1,3,1,2,1,1,1,1,2      },
+     {1070935,3,1,1,1,1,1,2,1,1,2      },
+     {1071760,2,1,1,1,2,1,3,1,1,2      },
+     {1072179,10,7,7,3,8,5,7,4,3,4     },
+     {1074610,2,1,1,2,2,1,3,1,1,2      },
+     {1075123,3,1,2,1,2,1,2,1,1,2      },
+     {1079304,2,1,1,1,2,1,2,1,1,2      },
+     {1080185,10,10,10,8,6,1,8,9,1,4   },
+     {1081791,6,2,1,1,1,1,7,1,1,2      },
+     {1084584,5,4,4,9,2,10,5,6,1,4     },
+     {1091262,2,5,3,3,6,7,7,5,1,4      },
+     {1096800,6,6,6,9,6,4,7,8,1,2      },
+     {1099510,10,4,3,1,3,3,6,5,2,4     },
+     {1100524,6,10,10,2,8,10,7,3,3,4   },
+     {1102573,5,6,5,6,10,1,3,1,1,4     },
+     {1103608,10,10,10,4,8,1,8,10,1,4  },
+     {1103722,1,1,1,1,2,1,2,1,2,2      },
+     {1105257,3,7,7,4,4,9,4,8,1,4      },
+     {1105524,1,1,1,1,2,1,2,1,1,2      },
+     {1106095,4,1,1,3,2,1,3,1,1,2      },
+     {1106829,7,8,7,2,4,8,3,8,2,4      },
+     {1108370,9,5,8,1,2,3,2,1,5,4      },
+     {1108449,5,3,3,4,2,4,3,4,1,4      },
+     {1110102,10,3,6,2,3,5,4,10,2,4    },
+     {1110503,5,5,5,8,10,8,7,3,7,4     },
+     {1110524,10,5,5,6,8,8,7,1,1,4     },
+     {1111249,10,6,6,3,4,5,3,6,1,4     },
+     {1112209,8,10,10,1,3,6,3,9,1,4    },
+     {1113038,8,2,4,1,5,1,5,4,4,4      },
+     {1113483,5,2,3,1,6,10,5,1,1,4     },
+     {1113906,9,5,5,2,2,2,5,1,1,4      },
+     {1115282,5,3,5,5,3,3,4,10,1,4     },
+     {1115293,1,1,1,1,2,2,2,1,1,2      },
+     {1116116,9,10,10,1,10,8,3,3,1,4   },
+     {1116132,6,3,4,1,5,2,3,9,1,4      },
+     {1116192,1,1,1,1,2,1,2,1,1,2      },
+     {1116998,10,4,2,1,3,2,4,3,10,4    },
+     {1117152,4,1,1,1,2,1,3,1,1,2      },
+     {1118039,5,3,4,1,8,10,4,9,1,4     },
+     {1120559,8,3,8,3,4,9,8,9,8,4      },
+     {1121732,1,1,1,1,2,1,3,2,1,2      },
+     {1121919,5,1,3,1,2,1,2,1,1,2      },
+     {1123061,6,10,2,8,10,2,7,8,10,4   },
+     {1124651,1,3,3,2,2,1,7,2,1,2      },
+     {1125035,9,4,5,10,6,10,4,8,1,4    },
+     {1126417,10,6,4,1,3,4,3,2,3,4     },
+     {1131294,1,1,2,1,2,2,4,2,1,2      },
+     {1132347,1,1,4,1,2,1,2,1,1,2      },
+     {1133041,5,3,1,2,2,1,2,1,1,2      },
+     {1133136,3,1,1,1,2,3,3,1,1,2      },
+     {1136142,2,1,1,1,3,1,2,1,1,2      },
+     {1137156,2,2,2,1,1,1,7,1,1,2      },
+     {1143978,4,1,1,2,2,1,2,1,1,2      },
+     {1143978,5,2,1,1,2,1,3,1,1,2      },
+     {1147044,3,1,1,1,2,2,7,1,1,2      },
+     {1147699,3,5,7,8,8,9,7,10,7,4     },
+     {1147748,5,10,6,1,10,4,4,10,10,4  },
+     {1148278,3,3,6,4,5,8,4,4,1,4      },
+     {1148873,3,6,6,6,5,10,6,8,3,4     },
+     {1152331,4,1,1,1,2,1,3,1,1,2      },
+     {1155546,2,1,1,2,3,1,2,1,1,2      },
+     {1156272,1,1,1,1,2,1,3,1,1,2      },
+     {1156948,3,1,1,2,2,1,1,1,1,2      },
+     {1157734,4,1,1,1,2,1,3,1,1,2      },
+     {1158247,1,1,1,1,2,1,2,1,1,2      },
+     {1160476,2,1,1,1,2,1,3,1,1,2      },
+     {1164066,1,1,1,1,2,1,3,1,1,2      },
+     {1165297,2,1,1,2,2,1,1,1,1,2      },
+     {1165790,5,1,1,1,2,1,3,1,1,2      },
+     {1165926,9,6,9,2,10,6,2,9,10,4    },
+     {1166630,7,5,6,10,5,10,7,9,4,4    },
+     {1166654,10,3,5,1,10,5,3,10,2,4   },
+     {1167439,2,3,4,4,2,5,2,5,1,4      },
+     {1167471,4,1,2,1,2,1,3,1,1,2      },
+     {1168359,8,2,3,1,6,3,7,1,1,4      },
+     {1168736,10,10,10,10,10,1,8,8,8,4 },
+     {1169049,7,3,4,4,3,3,3,2,7,4      },
+     {1170419,10,10,10,8,2,10,4,1,1,4  },
+     {1170420,1,6,8,10,8,10,5,7,1,4    },
+     {1171710,1,1,1,1,2,1,2,3,1,2      },
+     {1171710,6,5,4,4,3,9,7,8,3,4      },
+     {1171795,1,3,1,2,2,2,5,3,2,2      },
+     {1171845,8,6,4,3,5,9,3,1,1,4      },
+     {1172152,10,3,3,10,2,10,7,3,3,4   },
+     {1173216,10,10,10,3,10,8,8,1,1,4  },
+     {1173235,3,3,2,1,2,3,3,1,1,2      },
+     {1173347,1,1,1,1,2,5,1,1,1,2      },
+     {1173347,8,3,3,1,2,2,3,2,1,2      },
+     {1173509,4,5,5,10,4,10,7,5,8,4    },
+     {1173514,1,1,1,1,4,3,1,1,1,2      },
+     {1173681,3,2,1,1,2,2,3,1,1,2      },
+     {1174057,1,1,2,2,2,1,3,1,1,2      },
+     {1174057,4,2,1,1,2,2,3,1,1,2      },
+     {1174131,10,10,10,2,10,10,5,3,3,4 },
+     {1174428,5,3,5,1,8,10,5,3,1,4     },
+     {1175937,5,4,6,7,9,7,8,10,1,4     },
+     {1176406,1,1,1,1,2,1,2,1,1,2      },
+     {1176881,7,5,3,7,4,10,7,5,5,4        }
+};
+    private static readonly Dataset defaultDataset;
+    private static readonly IEnumerable<string> defaultAllowedInputVariables;
+    private static readonly string defaultTargetVariable;
+
+    private static readonly ClassificationProblemData emptyProblemData;
+    public static ClassificationProblemData EmptyProblemData {
+      get { return EmptyProblemData; }
+    }
+
+    static ClassificationProblemData() {
+      defaultDataset = new Dataset(defaultVariableNames, defaultData);
+      defaultDataset.Name = "Wisconsin classification problem";
+      defaultDataset.Description = "subset from to ..";
+
+      defaultAllowedInputVariables = defaultVariableNames.Except(new List<string>() { "sample", "class" });
+      defaultTargetVariable = "class";
+
+      var problemData = new ClassificationProblemData();
+      problemData.Parameters.Clear();
+      problemData.Name = "Empty Classification ProblemData";
+      problemData.Description = "This ProblemData acts as place holder before the correct problem data is loaded.";
+      problemData.isEmpty = true;
+
+      problemData.Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", new Dataset()));
+      problemData.Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>(InputVariablesParameterName, ""));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TrainingPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TestPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>()));
+      problemData.Parameters.Add(new FixedValueParameter<StringMatrix>(ClassNamesParameterName, "", new StringMatrix(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new FixedValueParameter<DoubleMatrix>(ClassificationPenaltiesParameterName, "", (DoubleMatrix)new DoubleMatrix(0, 0).AsReadOnly()));
+      emptyProblemData = problemData;
+    }
+    #endregion
+
+    #region parameter properties
+    public ConstrainedValueParameter<StringValue> TargetVariableParameter {
+      get { return (ConstrainedValueParameter<StringValue>)Parameters[TargetVariableParameterName]; }
+    }
+    public IFixedValueParameter<StringMatrix> ClassNamesParameter {
+      get { return (IFixedValueParameter<StringMatrix>)Parameters[ClassNamesParameterName]; }
+    }
+    public IFixedValueParameter<DoubleMatrix> ClassificationPenaltiesParameter {
+      get { return (IFixedValueParameter<DoubleMatrix>)Parameters[ClassificationPenaltiesParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public string TargetVariable {
+      get { return TargetVariableParameter.Value.Value; }
+    }
+
+    private List<double> classValues;
+    public List<double> ClassValues {
+      get {
+        if (classValues == null) {
+          classValues = Dataset.GetDoubleValues(TargetVariableParameter.Value.Value).Distinct().ToList();
+          classValues.Sort();
+        }
+        return classValues;
+      }
+    }
+    IEnumerable<double> IClassificationProblemData.ClassValues {
+      get { return ClassValues; }
+    }
+
+    public int Classes {
+      get { return ClassValues.Count; }
+    }
+
+    private List<string> classNames;
+    public List<string> ClassNames {
+      get {
+        if (classNames == null) {
+          classNames = new List<string>();
+          for (int i = 0; i < ClassNamesParameter.Value.Rows; i++)
+            classNames.Add(ClassNamesParameter.Value[i, 0]);
+        }
+        return classNames;
+      }
+    }
+    IEnumerable<string> IClassificationProblemData.ClassNames {
+      get { return ClassNames; }
+    }
+
+    private Dictionary<Tuple<double, double>, double> classificationPenaltiesCache = new Dictionary<Tuple<double, double>, double>();
+    #endregion
+
+
+    [StorableConstructor]
+    protected ClassificationProblemData(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterParameterEvents();
+    }
+
+    protected ClassificationProblemData(ClassificationProblemData original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterParameterEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      if (this == emptyProblemData) return emptyProblemData;
+      return new ClassificationProblemData(this, cloner);
+    }
+
+    public ClassificationProblemData() : this(defaultDataset, defaultAllowedInputVariables, defaultTargetVariable) { }
+    public ClassificationProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable)
+      : base(dataset, allowedInputVariables) {
+      var validTargetVariableValues = CheckVariablesForPossibleTargetVariables(dataset).Select(x => new StringValue(x).AsReadOnly()).ToList();
+      var target = validTargetVariableValues.Where(x => x.Value == targetVariable).DefaultIfEmpty(validTargetVariableValues.First()).First();
+
+      Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>(validTargetVariableValues), target));
+      Parameters.Add(new FixedValueParameter<StringMatrix>(ClassNamesParameterName, ""));
+      Parameters.Add(new FixedValueParameter<DoubleMatrix>(ClassificationPenaltiesParameterName, ""));
+
+      ResetTargetVariableDependentMembers();
+      RegisterParameterEvents();
+    }
+
+    private static IEnumerable<string> CheckVariablesForPossibleTargetVariables(Dataset dataset) {
+      int maxSamples = Math.Min(InspectedRowsToDetermineTargets, dataset.Rows);
+      var validTargetVariables = (from v in dataset.DoubleVariables
+                                  let distinctValues = dataset.GetDoubleValues(v)
+                                    .Take(maxSamples)
+                                    .Distinct()
+                                    .Count()
+                                  where distinctValues < MaximumNumberOfClasses
+                                  select v).ToArray();
+
+      if (!validTargetVariables.Any())
+        throw new ArgumentException("Import of classification problem data was not successful, because no target variable was found." +
+          " A target variable must have at most " + MaximumNumberOfClasses + " distinct values to be applicable to classification.");
+      return validTargetVariables;
+    }
+
+
+    private void ResetTargetVariableDependentMembers() {
+      DeregisterParameterEvents();
+
+      classNames = null;
+      ((IStringConvertibleMatrix)ClassNamesParameter.Value).Columns = 1;
+      ((IStringConvertibleMatrix)ClassNamesParameter.Value).Rows = ClassValues.Count;
+      for (int i = 0; i < Classes; i++)
+        ClassNamesParameter.Value[i, 0] = "Class " + ClassValues[i];
+      ClassNamesParameter.Value.ColumnNames = new List<string>() { "ClassNames" };
+      ClassNamesParameter.Value.RowNames = ClassValues.Select(s => "ClassValue: " + s);
+
+      classificationPenaltiesCache.Clear();
+      ((ValueParameter<DoubleMatrix>)ClassificationPenaltiesParameter).ReactOnValueToStringChangedAndValueItemImageChanged = false;
+      ((IStringConvertibleMatrix)ClassificationPenaltiesParameter.Value).Rows = Classes;
+      ((IStringConvertibleMatrix)ClassificationPenaltiesParameter.Value).Columns = Classes;
+      ClassificationPenaltiesParameter.Value.RowNames = ClassNames.Select(name => "Actual " + name);
+      ClassificationPenaltiesParameter.Value.ColumnNames = ClassNames.Select(name => "Estimated " + name);
+      for (int i = 0; i < Classes; i++) {
+        for (int j = 0; j < Classes; j++) {
+          if (i != j) ClassificationPenaltiesParameter.Value[i, j] = 1;
+          else ClassificationPenaltiesParameter.Value[i, j] = 0;
+        }
+      }
+      ((ValueParameter<DoubleMatrix>)ClassificationPenaltiesParameter).ReactOnValueToStringChangedAndValueItemImageChanged = true;
+      RegisterParameterEvents();
+    }
+
+    public string GetClassName(double classValue) {
+      if (!ClassValues.Contains(classValue)) throw new ArgumentException();
+      int index = ClassValues.IndexOf(classValue);
+      return ClassNames[index];
+    }
+    public double GetClassValue(string className) {
+      if (!ClassNames.Contains(className)) throw new ArgumentException();
+      int index = ClassNames.IndexOf(className);
+      return ClassValues[index];
+    }
+    public void SetClassName(double classValue, string className) {
+      if (!classValues.Contains(classValue)) throw new ArgumentException();
+      int index = ClassValues.IndexOf(classValue);
+      ClassNames[index] = className;
+      ClassNamesParameter.Value[index, 0] = className;
+    }
+
+    public double GetClassificationPenalty(string correctClassName, string estimatedClassName) {
+      return GetClassificationPenalty(GetClassValue(correctClassName), GetClassValue(estimatedClassName));
+    }
+    public double GetClassificationPenalty(double correctClassValue, double estimatedClassValue) {
+      var key = Tuple.Create(correctClassValue, estimatedClassValue);
+      if (!classificationPenaltiesCache.ContainsKey(key)) {
+        int correctClassIndex = ClassValues.IndexOf(correctClassValue);
+        int estimatedClassIndex = ClassValues.IndexOf(estimatedClassValue);
+        classificationPenaltiesCache[key] = ClassificationPenaltiesParameter.Value[correctClassIndex, estimatedClassIndex];
+      }
+      return classificationPenaltiesCache[key];
+    }
+    public void SetClassificationPenalty(string correctClassName, string estimatedClassName, double penalty) {
+      SetClassificationPenalty(GetClassValue(correctClassName), GetClassValue(estimatedClassName), penalty);
+    }
+    public void SetClassificationPenalty(double correctClassValue, double estimatedClassValue, double penalty) {
+      var key = Tuple.Create(correctClassValue, estimatedClassValue);
+      int correctClassIndex = ClassValues.IndexOf(correctClassValue);
+      int estimatedClassIndex = ClassValues.IndexOf(estimatedClassValue);
+
+      ClassificationPenaltiesParameter.Value[correctClassIndex, estimatedClassIndex] = penalty;
+    }
+
+    #region events
+    private void RegisterParameterEvents() {
+      TargetVariableParameter.ValueChanged += new EventHandler(TargetVariableParameter_ValueChanged);
+      ClassNamesParameter.Value.Reset += new EventHandler(Parameter_ValueChanged);
+      ClassNamesParameter.Value.ItemChanged += new EventHandler<EventArgs<int, int>>(MatrixParameter_ItemChanged);
+      ClassificationPenaltiesParameter.Value.Reset += new EventHandler(Parameter_ValueChanged);
+      ClassificationPenaltiesParameter.Value.ItemChanged += new EventHandler<EventArgs<int, int>>(MatrixParameter_ItemChanged);
+    }
+    private void DeregisterParameterEvents() {
+      TargetVariableParameter.ValueChanged -= new EventHandler(TargetVariableParameter_ValueChanged);
+      ClassNamesParameter.Value.Reset -= new EventHandler(Parameter_ValueChanged);
+      ClassNamesParameter.Value.ItemChanged -= new EventHandler<EventArgs<int, int>>(MatrixParameter_ItemChanged);
+      ClassificationPenaltiesParameter.Value.Reset -= new EventHandler(Parameter_ValueChanged);
+      ClassificationPenaltiesParameter.Value.ItemChanged -= new EventHandler<EventArgs<int, int>>(MatrixParameter_ItemChanged);
+    }
+
+    private void TargetVariableParameter_ValueChanged(object sender, EventArgs e) {
+      classValues = null;
+      ResetTargetVariableDependentMembers();
+      OnChanged();
+    }
+    private void Parameter_ValueChanged(object sender, EventArgs e) {
+      OnChanged();
+    }
+    private void MatrixParameter_ItemChanged(object sender, EventArgs<int, int> e) {
+      OnChanged();
+    }
+    #endregion
+
+    #region Import from file
+    public static ClassificationProblemData ImportFromFile(string fileName) {
+      TableFileParser csvFileParser = new TableFileParser();
+      csvFileParser.Parse(fileName);
+
+      Dataset dataset = new Dataset(csvFileParser.VariableNames, csvFileParser.Values);
+      dataset.Name = Path.GetFileName(fileName);
+
+      ClassificationProblemData problemData = new ClassificationProblemData(dataset, dataset.DoubleVariables.Skip(1), dataset.DoubleVariables.First());
+      problemData.Name = "Data imported from " + Path.GetFileName(fileName);
+      return problemData;
+    }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs	(revision 7570)
@@ -0,0 +1,81 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a classification data analysis solution
+  /// </summary>
+  [StorableClass]
+  public abstract class ClassificationSolution : ClassificationSolutionBase {
+    protected readonly Dictionary<int, double> evaluationCache;
+
+    [StorableConstructor]
+    protected ClassificationSolution(bool deserializing)
+      : base(deserializing) {
+      evaluationCache = new Dictionary<int, double>();
+    }
+    protected ClassificationSolution(ClassificationSolution original, Cloner cloner)
+      : base(original, cloner) {
+      evaluationCache = new Dictionary<int, double>(original.evaluationCache);
+    }
+    public ClassificationSolution(IClassificationModel model, IClassificationProblemData problemData)
+      : base(model, problemData) {
+      evaluationCache = new Dictionary<int, double>();
+    }
+
+    public override IEnumerable<double> EstimatedClassValues {
+      get { return GetEstimatedClassValues(Enumerable.Range(0, ProblemData.Dataset.Rows)); }
+    }
+    public override IEnumerable<double> EstimatedTrainingClassValues {
+      get { return GetEstimatedClassValues(ProblemData.TrainingIndizes); }
+    }
+    public override IEnumerable<double> EstimatedTestClassValues {
+      get { return GetEstimatedClassValues(ProblemData.TestIndizes); }
+    }
+
+    public override IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows) {
+      var rowsToEvaluate = rows.Except(evaluationCache.Keys);
+      var rowsEnumerator = rowsToEvaluate.GetEnumerator();
+      var valuesEnumerator = Model.GetEstimatedClassValues(ProblemData.Dataset, rowsToEvaluate).GetEnumerator();
+
+      while (rowsEnumerator.MoveNext() & valuesEnumerator.MoveNext()) {
+        evaluationCache.Add(rowsEnumerator.Current, valuesEnumerator.Current);
+      }
+
+      return rows.Select(row => evaluationCache[row]);
+    }
+
+    protected override void OnProblemDataChanged() {
+      evaluationCache.Clear();
+      base.OnProblemDataChanged();
+    }
+
+    protected override void OnModelChanged() {
+      evaluationCache.Clear();
+      base.OnModelChanged();
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionBase.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionBase.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolutionBase.cs	(revision 7570)
@@ -0,0 +1,117 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  public abstract class ClassificationSolutionBase : DataAnalysisSolution, IClassificationSolution {
+    private const string TrainingAccuracyResultName = "Accuracy (training)";
+    private const string TestAccuracyResultName = "Accuracy (test)";
+    private const string TrainingNormalizedGiniCoefficientResultName = "Normalized Gini Coefficient (training)";
+    private const string TestNormalizedGiniCoefficientResultName = "Normalized Gini Coefficient (test)";
+
+    public new IClassificationModel Model {
+      get { return (IClassificationModel)base.Model; }
+      protected set { base.Model = value; }
+    }
+
+    public new IClassificationProblemData ProblemData {
+      get { return (IClassificationProblemData)base.ProblemData; }
+      set { base.ProblemData = value; }
+    }
+
+    #region Results
+    public double TrainingAccuracy {
+      get { return ((DoubleValue)this[TrainingAccuracyResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingAccuracyResultName].Value).Value = value; }
+    }
+    public double TestAccuracy {
+      get { return ((DoubleValue)this[TestAccuracyResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestAccuracyResultName].Value).Value = value; }
+    }
+    public double TrainingNormalizedGiniCoefficient {
+      get { return ((DoubleValue)this[TrainingNormalizedGiniCoefficientResultName].Value).Value; }
+      protected set { ((DoubleValue)this[TrainingNormalizedGiniCoefficientResultName].Value).Value = value; }
+    }
+    public double TestNormalizedGiniCoefficient {
+      get { return ((DoubleValue)this[TestNormalizedGiniCoefficientResultName].Value).Value; }
+      protected set { ((DoubleValue)this[TestNormalizedGiniCoefficientResultName].Value).Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ClassificationSolutionBase(bool deserializing) : base(deserializing) { }
+    protected ClassificationSolutionBase(ClassificationSolutionBase original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    protected ClassificationSolutionBase(IClassificationModel model, IClassificationProblemData problemData)
+      : base(model, problemData) {
+      Add(new Result(TrainingAccuracyResultName, "Accuracy of the model on the training partition (percentage of correctly classified instances).", new PercentValue()));
+      Add(new Result(TestAccuracyResultName, "Accuracy of the model on the test partition (percentage of correctly classified instances).", new PercentValue()));
+      Add(new Result(TrainingNormalizedGiniCoefficientResultName, "Normalized Gini coefficient of the model on the training partition.", new DoubleValue()));
+      Add(new Result(TestNormalizedGiniCoefficientResultName, "Normalized Gini coefficient of the model on the test partition.", new DoubleValue()));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!this.ContainsKey(TrainingNormalizedGiniCoefficientResultName))
+        Add(new Result(TrainingNormalizedGiniCoefficientResultName, "Normalized Gini coefficient of the model on the training partition.", new DoubleValue()));
+      if (!this.ContainsKey(TestNormalizedGiniCoefficientResultName))
+        Add(new Result(TestNormalizedGiniCoefficientResultName, "Normalized Gini coefficient of the model on the test partition.", new DoubleValue()));
+    }
+
+    protected void CalculateResults() {
+      double[] estimatedTrainingClassValues = EstimatedTrainingClassValues.ToArray(); // cache values
+      double[] originalTrainingClassValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes).ToArray();
+      double[] estimatedTestClassValues = EstimatedTestClassValues.ToArray(); // cache values
+      double[] originalTestClassValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TestIndizes).ToArray();
+
+      OnlineCalculatorError errorState;
+      double trainingAccuracy = OnlineAccuracyCalculator.Calculate(originalTrainingClassValues, estimatedTrainingClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) trainingAccuracy = double.NaN;
+      double testAccuracy = OnlineAccuracyCalculator.Calculate(originalTestClassValues, estimatedTestClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) testAccuracy = double.NaN;
+
+      TrainingAccuracy = trainingAccuracy;
+      TestAccuracy = testAccuracy;
+
+      double trainingNormalizedGini = NormalizedGiniCalculator.Calculate(originalTrainingClassValues, estimatedTrainingClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) trainingNormalizedGini = double.NaN;
+      double testNormalizedGini = NormalizedGiniCalculator.Calculate(originalTestClassValues, estimatedTestClassValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) testNormalizedGini = double.NaN;
+
+      TrainingNormalizedGiniCoefficient = trainingNormalizedGini;
+      TestNormalizedGiniCoefficient = testNormalizedGini;
+    }
+
+    public abstract IEnumerable<double> EstimatedClassValues { get; }
+    public abstract IEnumerable<double> EstimatedTrainingClassValues { get; }
+    public abstract IEnumerable<double> EstimatedTestClassValues { get; }
+
+    public abstract IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs	(revision 7570)
@@ -0,0 +1,108 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents discriminant function classification data analysis models.
+  /// </summary>
+  [StorableClass]
+  [Item("DiscriminantFunctionClassificationModel", "Represents a classification model that uses a discriminant function and classification thresholds.")]
+  public abstract class DiscriminantFunctionClassificationModel : NamedItem, IDiscriminantFunctionClassificationModel {
+    [Storable]
+    private IRegressionModel model;
+
+    [Storable]
+    private double[] classValues;
+    public IEnumerable<double> ClassValues {
+      get { return (double[])classValues.Clone(); }
+      private set { classValues = value.ToArray(); }
+    }
+
+    [Storable]
+    private double[] thresholds;
+    public IEnumerable<double> Thresholds {
+      get { return (IEnumerable<double>)thresholds.Clone(); }
+      private set { thresholds = value.ToArray(); }
+    }
+
+
+    [StorableConstructor]
+    protected DiscriminantFunctionClassificationModel(bool deserializing) : base(deserializing) { }
+    protected DiscriminantFunctionClassificationModel(DiscriminantFunctionClassificationModel original, Cloner cloner)
+      : base(original, cloner) {
+      model = cloner.Clone(original.model);
+      classValues = (double[])original.classValues.Clone();
+      thresholds = (double[])original.thresholds.Clone();
+    }
+
+    public DiscriminantFunctionClassificationModel(IRegressionModel model)
+      : base() {
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.model = model;
+      this.classValues = new double[] { 0.0 };
+      this.thresholds = new double[] { double.NegativeInfinity };
+    }
+
+    public void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues) {
+      var classValuesArr = classValues.ToArray();
+      var thresholdsArr = thresholds.ToArray();
+      if (thresholdsArr.Length != classValuesArr.Length) throw new ArgumentException();
+
+      this.classValues = classValuesArr;
+      this.thresholds = thresholdsArr;
+      OnThresholdsChanged(EventArgs.Empty);
+    }
+
+    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+      return model.GetEstimatedValues(dataset, rows);
+    }
+
+    public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
+      foreach (var x in GetEstimatedValues(dataset, rows)) {
+        int classIndex = 0;
+        // find first threshold value which is larger than x => class index = threshold index + 1
+        for (int i = 0; i < thresholds.Length; i++) {
+          if (x > thresholds[i]) classIndex++;
+          else break;
+        }
+        yield return classValues.ElementAt(classIndex - 1);
+      }
+    }
+    #region events
+    public event EventHandler ThresholdsChanged;
+    protected virtual void OnThresholdsChanged(EventArgs e) {
+      var listener = ThresholdsChanged;
+      if (listener != null) listener(this, e);
+    }
+    #endregion
+
+    public abstract IDiscriminantFunctionClassificationSolution CreateDiscriminantFunctionClassificationSolution(IClassificationProblemData problemData);
+    public abstract IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs	(revision 7570)
@@ -0,0 +1,117 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a classification solution that uses a discriminant function and classification thresholds.
+  /// </summary>
+  [StorableClass]
+  [Item("DiscriminantFunctionClassificationSolution", "Represents a classification solution that uses a discriminant function and classification thresholds.")]
+  public abstract class DiscriminantFunctionClassificationSolution : DiscriminantFunctionClassificationSolutionBase {
+    protected readonly Dictionary<int, double> valueEvaluationCache;
+    protected readonly Dictionary<int, double> classValueEvaluationCache;
+
+    [StorableConstructor]
+    protected DiscriminantFunctionClassificationSolution(bool deserializing)
+      : base(deserializing) {
+      valueEvaluationCache = new Dictionary<int, double>();
+      classValueEvaluationCache = new Dictionary<int, double>();
+    }
+    protected DiscriminantFunctionClassificationSolution(DiscriminantFunctionClassificationSolution original, Cloner cloner)
+      : base(original, cloner) {
+      valueEvaluationCache = new Dictionary<int, double>(original.valueEvaluationCache);
+      classValueEvaluationCache = new Dictionary<int, double>(original.classValueEvaluationCache);
+    }
+    protected DiscriminantFunctionClassificationSolution(IDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData)
+      : base(model, problemData) {
+      valueEvaluationCache = new Dictionary<int, double>();
+      classValueEvaluationCache = new Dictionary<int, double>();
+
+      SetAccuracyMaximizingThresholds();
+    }
+
+    public override IEnumerable<double> EstimatedClassValues {
+      get { return GetEstimatedClassValues(Enumerable.Range(0, ProblemData.Dataset.Rows)); }
+    }
+    public override IEnumerable<double> EstimatedTrainingClassValues {
+      get { return GetEstimatedClassValues(ProblemData.TrainingIndizes); }
+    }
+    public override IEnumerable<double> EstimatedTestClassValues {
+      get { return GetEstimatedClassValues(ProblemData.TestIndizes); }
+    }
+
+    public override IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows) {
+      var rowsToEvaluate = rows.Except(classValueEvaluationCache.Keys);
+      var rowsEnumerator = rowsToEvaluate.GetEnumerator();
+      var valuesEnumerator = Model.GetEstimatedClassValues(ProblemData.Dataset, rowsToEvaluate).GetEnumerator();
+
+      while (rowsEnumerator.MoveNext() & valuesEnumerator.MoveNext()) {
+        classValueEvaluationCache.Add(rowsEnumerator.Current, valuesEnumerator.Current);
+      }
+
+      return rows.Select(row => classValueEvaluationCache[row]);
+    }
+
+
+    public override IEnumerable<double> EstimatedValues {
+      get { return GetEstimatedValues(Enumerable.Range(0, ProblemData.Dataset.Rows)); }
+    }
+    public override IEnumerable<double> EstimatedTrainingValues {
+      get { return GetEstimatedValues(ProblemData.TrainingIndizes); }
+    }
+    public override IEnumerable<double> EstimatedTestValues {
+      get { return GetEstimatedValues(ProblemData.TestIndizes); }
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows) {
+      var rowsToEvaluate = rows.Except(valueEvaluationCache.Keys);
+      var rowsEnumerator = rowsToEvaluate.GetEnumerator();
+      var valuesEnumerator = Model.GetEstimatedValues(ProblemData.Dataset, rowsToEvaluate).GetEnumerator();
+
+      while (rowsEnumerator.MoveNext() & valuesEnumerator.MoveNext()) {
+        valueEvaluationCache.Add(rowsEnumerator.Current, valuesEnumerator.Current);
+      }
+
+      return rows.Select(row => valueEvaluationCache[row]);
+    }
+
+    protected override void OnModelChanged() {
+      valueEvaluationCache.Clear();
+      classValueEvaluationCache.Clear();
+      base.OnModelChanged();
+    }
+    protected override void OnModelThresholdsChanged(System.EventArgs e) {
+      classValueEvaluationCache.Clear();
+      base.OnModelThresholdsChanged(e);
+    }
+    protected override void OnProblemDataChanged() {
+      valueEvaluationCache.Clear();
+      classValueEvaluationCache.Clear();
+      base.OnProblemDataChanged();
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolutionBase.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolutionBase.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolutionBase.cs	(revision 7570)
@@ -0,0 +1,168 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a classification solution that uses a discriminant function and classification thresholds.
+  /// </summary>
+  [StorableClass]
+  [Item("DiscriminantFunctionClassificationSolution", "Represents a classification solution that uses a discriminant function and classification thresholds.")]
+  public abstract class DiscriminantFunctionClassificationSolutionBase : ClassificationSolutionBase, IDiscriminantFunctionClassificationSolution {
+    private const string TrainingMeanSquaredErrorResultName = "Mean squared error (training)";
+    private const string TestMeanSquaredErrorResultName = "Mean squared error (test)";
+    private const string TrainingRSquaredResultName = "Pearson's R² (training)";
+    private const string TestRSquaredResultName = "Pearson's R² (test)";
+
+    public new IDiscriminantFunctionClassificationModel Model {
+      get { return (IDiscriminantFunctionClassificationModel)base.Model; }
+      protected set {
+        if (value != null && value != Model) {
+          if (Model != null) {
+            Model.ThresholdsChanged -= new EventHandler(Model_ThresholdsChanged);
+          }
+          value.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
+          base.Model = value;
+        }
+      }
+    }
+
+    #region Results
+    public double TrainingMeanSquaredError {
+      get { return ((DoubleValue)this[TrainingMeanSquaredErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingMeanSquaredErrorResultName].Value).Value = value; }
+    }
+    public double TestMeanSquaredError {
+      get { return ((DoubleValue)this[TestMeanSquaredErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestMeanSquaredErrorResultName].Value).Value = value; }
+    }
+    public double TrainingRSquared {
+      get { return ((DoubleValue)this[TrainingRSquaredResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingRSquaredResultName].Value).Value = value; }
+    }
+    public double TestRSquared {
+      get { return ((DoubleValue)this[TestRSquaredResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestRSquaredResultName].Value).Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected DiscriminantFunctionClassificationSolutionBase(bool deserializing) : base(deserializing) { }
+    protected DiscriminantFunctionClassificationSolutionBase(DiscriminantFunctionClassificationSolutionBase original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandler();
+    }
+    protected DiscriminantFunctionClassificationSolutionBase(IDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData)
+      : base(model, problemData) {
+      Add(new Result(TrainingMeanSquaredErrorResultName, "Mean of squared errors of the model on the training partition", new DoubleValue()));
+      Add(new Result(TestMeanSquaredErrorResultName, "Mean of squared errors of the model on the test partition", new DoubleValue()));
+      Add(new Result(TrainingRSquaredResultName, "Squared Pearson's correlation coefficient of the model output and the actual values on the training partition", new DoubleValue()));
+      Add(new Result(TestRSquaredResultName, "Squared Pearson's correlation coefficient of the model output and the actual values on the test partition", new DoubleValue()));
+
+      RegisterEventHandler();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandler();
+    }
+
+    protected override void OnModelChanged() {
+      DeregisterEventHandler();
+      SetAccuracyMaximizingThresholds();
+      RegisterEventHandler();
+      base.OnModelChanged();
+    }
+
+    protected void CalculateRegressionResults() {
+      double[] estimatedTrainingValues = EstimatedTrainingValues.ToArray(); // cache values
+      double[] originalTrainingValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes).ToArray();
+      double[] estimatedTestValues = EstimatedTestValues.ToArray(); // cache values
+      double[] originalTestValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TestIndizes).ToArray();
+
+      OnlineCalculatorError errorState;
+      double trainingMSE = OnlineMeanSquaredErrorCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingMeanSquaredError = errorState == OnlineCalculatorError.None ? trainingMSE : double.NaN;
+      double testMSE = OnlineMeanSquaredErrorCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestMeanSquaredError = errorState == OnlineCalculatorError.None ? testMSE : double.NaN;
+
+      double trainingR2 = OnlinePearsonsRSquaredCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingRSquared = errorState == OnlineCalculatorError.None ? trainingR2 : double.NaN;
+      double testR2 = OnlinePearsonsRSquaredCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestRSquared = errorState == OnlineCalculatorError.None ? testR2 : double.NaN;
+
+      double trainingNormalizedGini = NormalizedGiniCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) trainingNormalizedGini = double.NaN;
+      double testNormalizedGini = NormalizedGiniCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      if (errorState != OnlineCalculatorError.None) testNormalizedGini = double.NaN;
+
+      TrainingNormalizedGiniCoefficient = trainingNormalizedGini;
+      TestNormalizedGiniCoefficient = testNormalizedGini;
+    }
+
+    private void RegisterEventHandler() {
+      Model.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
+    }
+    private void DeregisterEventHandler() {
+      Model.ThresholdsChanged -= new EventHandler(Model_ThresholdsChanged);
+    }
+    private void Model_ThresholdsChanged(object sender, EventArgs e) {
+      OnModelThresholdsChanged(e);
+    }
+
+    public void SetAccuracyMaximizingThresholds() {
+      double[] classValues;
+      double[] thresholds;
+      var targetClassValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
+      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, EstimatedTrainingValues, targetClassValues, out classValues, out thresholds);
+
+      Model.SetThresholdsAndClassValues(thresholds, classValues);
+    }
+
+    public void SetClassDistibutionCutPointThresholds() {
+      double[] classValues;
+      double[] thresholds;
+      var targetClassValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
+      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(ProblemData, EstimatedTrainingValues, targetClassValues, out classValues, out thresholds);
+
+      Model.SetThresholdsAndClassValues(thresholds, classValues);
+    }
+
+    protected virtual void OnModelThresholdsChanged(EventArgs e) {
+      CalculateResults();
+      CalculateRegressionResults();
+    }
+
+    public abstract IEnumerable<double> EstimatedValues { get; }
+    public abstract IEnumerable<double> EstimatedTrainingValues { get; }
+    public abstract IEnumerable<double> EstimatedTestValues { get; }
+
+    public abstract IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs	(revision 7570)
@@ -0,0 +1,128 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a threshold calculator that maximizes the weighted accuracy of the classifcation model.
+  /// </summary>
+  [StorableClass]
+  [Item("AccuracyMaximizationThresholdCalculator", "Represents a threshold calculator that maximizes the weighted accuracy of the classifcation model.")]
+  public class AccuracyMaximizationThresholdCalculator : ThresholdCalculator {
+
+    [StorableConstructor]
+    protected AccuracyMaximizationThresholdCalculator(bool deserializing) : base(deserializing) { }
+    protected AccuracyMaximizationThresholdCalculator(AccuracyMaximizationThresholdCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public AccuracyMaximizationThresholdCalculator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new AccuracyMaximizationThresholdCalculator(this, cloner);
+    }
+
+    public override void Calculate(IClassificationProblemData problemData, IEnumerable<double> estimatedValues, IEnumerable<double> targetClassValues, out double[] classValues, out double[] thresholds) {
+      AccuracyMaximizationThresholdCalculator.CalculateThresholds(problemData, estimatedValues, targetClassValues, out classValues, out thresholds);
+    }
+
+    public static void CalculateThresholds(IClassificationProblemData problemData, IEnumerable<double> estimatedValues, IEnumerable<double> targetClassValues, out double[] classValues, out double[] thresholds) {
+      int slices = 100;
+      List<double> estimatedValuesList = estimatedValues.ToList();
+      double maxEstimatedValue = estimatedValuesList.Max();
+      double minEstimatedValue = estimatedValuesList.Min();
+      double thresholdIncrement = (maxEstimatedValue - minEstimatedValue) / slices;
+      var estimatedAndTargetValuePairs =
+        estimatedValuesList.Zip(targetClassValues, (x, y) => new { EstimatedValue = x, TargetClassValue = y })
+        .OrderBy(x => x.EstimatedValue)
+        .ToList();
+
+      classValues = problemData.ClassValues.OrderBy(x => x).ToArray();
+      int nClasses = classValues.Length;
+      thresholds = new double[nClasses];
+      thresholds[0] = double.NegativeInfinity;
+      // thresholds[thresholds.Length - 1] = double.PositiveInfinity;
+
+      // incrementally calculate accuracy of all possible thresholds
+      int[,] confusionMatrix = new int[nClasses, nClasses];
+
+      for (int i = 1; i < thresholds.Length; i++) {
+        double lowerThreshold = thresholds[i - 1];
+        double actualThreshold = Math.Max(lowerThreshold, minEstimatedValue);
+        double lowestBestThreshold = double.NaN;
+        double highestBestThreshold = double.NaN;
+        double bestClassificationScore = double.PositiveInfinity;
+        bool seriesOfEqualClassificationScores = false;
+
+        while (actualThreshold < maxEstimatedValue) {
+          double classificationScore = 0.0;
+
+          foreach (var pair in estimatedAndTargetValuePairs) {
+            //all positives
+            if (pair.TargetClassValue.IsAlmost(classValues[i - 1])) {
+              if (pair.EstimatedValue > lowerThreshold && pair.EstimatedValue < actualThreshold)
+                //true positive
+                classificationScore += problemData.GetClassificationPenalty(classValues[i - 1], classValues[i - 1]);
+              else
+                //false negative
+                classificationScore += problemData.GetClassificationPenalty(classValues[i], classValues[i - 1]);
+            }
+              //all negatives
+            else {
+              if (pair.EstimatedValue > lowerThreshold && pair.EstimatedValue < actualThreshold)
+                //false positive
+                classificationScore += problemData.GetClassificationPenalty(classValues[i - 1], classValues[i]);
+              else
+                //true negative, consider only upper class
+                classificationScore += problemData.GetClassificationPenalty(classValues[i], classValues[i]);
+            }
+          }
+
+          //new best classification score found
+          if (classificationScore < bestClassificationScore) {
+            bestClassificationScore = classificationScore;
+            lowestBestThreshold = actualThreshold;
+            highestBestThreshold = actualThreshold;
+            seriesOfEqualClassificationScores = true;
+          }
+            //equal classification scores => if seriesOfEqualClassifcationScores == true update highest threshold
+          else if (Math.Abs(classificationScore - bestClassificationScore) < double.Epsilon && seriesOfEqualClassificationScores)
+            highestBestThreshold = actualThreshold;
+          //worse classificatoin score found reset seriesOfEqualClassifcationScores
+          else seriesOfEqualClassificationScores = false;
+
+          actualThreshold += thresholdIncrement;
+        }
+        //scale lowest thresholds and highest found optimal threshold according to the misclassification matrix
+        double falseNegativePenalty = problemData.GetClassificationPenalty(classValues[i], classValues[i - 1]);
+        double falsePositivePenalty = problemData.GetClassificationPenalty(classValues[i - 1], classValues[i]);
+        thresholds[i] = (lowestBestThreshold * falsePositivePenalty + highestBestThreshold * falseNegativePenalty) / (falseNegativePenalty + falsePositivePenalty);
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs	(revision 7570)
@@ -0,0 +1,155 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a threshold calculator that calculates thresholds as the cutting points between the estimated class distributions (assuming normally distributed class values).
+  /// </summary>
+  [StorableClass]
+  [Item("NormalDistributionCutPointsThresholdCalculator", "Represents a threshold calculator that calculates thresholds as the cutting points between the estimated class distributions (assuming normally distributed class values).")]
+  public class NormalDistributionCutPointsThresholdCalculator : ThresholdCalculator {
+
+    [StorableConstructor]
+    protected NormalDistributionCutPointsThresholdCalculator(bool deserializing) : base(deserializing) { }
+    protected NormalDistributionCutPointsThresholdCalculator(NormalDistributionCutPointsThresholdCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public NormalDistributionCutPointsThresholdCalculator()
+      : base() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NormalDistributionCutPointsThresholdCalculator(this, cloner);
+    }
+
+    public override void Calculate(IClassificationProblemData problemData, IEnumerable<double> estimatedValues, IEnumerable<double> targetClassValues, out double[] classValues, out double[] thresholds) {
+      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(problemData, estimatedValues, targetClassValues, out classValues, out thresholds);
+    }
+
+    public static void CalculateThresholds(IClassificationProblemData problemData, IEnumerable<double> estimatedValues, IEnumerable<double> targetClassValues, out double[] classValues, out double[] thresholds) {
+      double maxEstimatedValue = estimatedValues.Max();
+      double minEstimatedValue = estimatedValues.Min();
+      var estimatedTargetValues = Enumerable.Zip(estimatedValues, targetClassValues, (e, t) => new { EstimatedValue = e, TargetValue = t }).ToList();
+
+      Dictionary<double, double> classMean = new Dictionary<double, double>();
+      Dictionary<double, double> classStdDev = new Dictionary<double, double>();
+      // calculate moments per class
+      foreach (var group in estimatedTargetValues.GroupBy(p => p.TargetValue)) {
+        IEnumerable<double> estimatedClassValues = group.Select(x => x.EstimatedValue);
+        double classValue = group.Key;
+        double mean, variance;
+        OnlineCalculatorError meanErrorState, varianceErrorState;
+        OnlineMeanAndVarianceCalculator.Calculate(estimatedClassValues, out mean, out variance, out meanErrorState, out varianceErrorState);
+
+        if (meanErrorState == OnlineCalculatorError.None && varianceErrorState == OnlineCalculatorError.None) {
+          classMean[classValue] = mean;
+          classStdDev[classValue] = Math.Sqrt(variance);
+        }
+      }
+      double[] originalClasses = classMean.Keys.OrderBy(x => x).ToArray();
+      int nClasses = originalClasses.Length;
+      List<double> thresholdList = new List<double>();
+      for (int i = 0; i < nClasses - 1; i++) {
+        for (int j = i + 1; j < nClasses; j++) {
+          double x1, x2;
+          double class0 = originalClasses[i];
+          double class1 = originalClasses[j];
+          // calculate all thresholds
+          CalculateCutPoints(classMean[class0], classStdDev[class0], classMean[class1], classStdDev[class1], out x1, out x2);
+          if (!thresholdList.Any(x => x.IsAlmost(x1))) thresholdList.Add(x1);
+          if (!thresholdList.Any(x => x.IsAlmost(x2))) thresholdList.Add(x2);
+        }
+      }
+      thresholdList.Sort();
+      thresholdList.Insert(0, double.NegativeInfinity);
+
+      // determine class values for each partition separated by a threshold by calculating the density of all class distributions
+      // all points in the partition are classified as the class with the maximal density in the parition
+      List<double> classValuesList = new List<double>();
+      for (int i = 0; i < thresholdList.Count; i++) {
+        double m;
+        if (double.IsNegativeInfinity(thresholdList[i])) {
+          m = thresholdList[i + 1] - 1.0; // smaller than the smalles non-infinity threshold
+        } else if (i == thresholdList.Count - 1) {
+          // last threshold
+          m = thresholdList[i] + 1.0; // larger than the last threshold
+        } else {
+          m = thresholdList[i] + (thresholdList[i + 1] - thresholdList[i]) / 2.0; // middle of partition
+        }
+
+        // determine class with maximal probability density in m
+        double maxDensity = double.MinValue;
+        double maxDensityClassValue = -1;
+        foreach (var classValue in originalClasses) {
+          double density = NormalDensity(m, classMean[classValue], classStdDev[classValue]);
+          if (density > maxDensity) {
+            maxDensity = density;
+            maxDensityClassValue = classValue;
+          }
+        }
+        classValuesList.Add(maxDensityClassValue);
+      }
+
+      // only keep thresholds at which the class changes 
+      // class B overrides threshold s. So only thresholds r and t are relevant and have to be kept
+      // 
+      //      A    B  C
+      //       /\  /\/\        
+      //      / r\/ /\t\       
+      //     /   /\/  \ \      
+      //    /   / /\s  \ \     
+      //  -/---/-/ -\---\-\----
+      List<double> filteredThresholds = new List<double>();
+      List<double> filteredClassValues = new List<double>();
+      filteredThresholds.Add(thresholdList[0]);
+      filteredClassValues.Add(classValuesList[0]);
+      for (int i = 0; i < classValuesList.Count - 1; i++) {
+        if (classValuesList[i] != classValuesList[i + 1]) {
+          filteredThresholds.Add(thresholdList[i + 1]);
+          filteredClassValues.Add(classValuesList[i + 1]);
+        }
+      }
+      thresholds = filteredThresholds.ToArray();
+      classValues = filteredClassValues.ToArray();
+    }
+
+    private static double NormalDensity(double x, double mu, double sigma) {
+      if (sigma.IsAlmost(0.0)) {
+        if (x.IsAlmost(mu)) return 1.0; else return 0.0;
+      } else {
+        return (1.0 / Math.Sqrt(2.0 * Math.PI * sigma * sigma)) * Math.Exp(-((x - mu) * (x - mu)) / (2.0 * sigma * sigma));
+      }
+    }
+
+    private static void CalculateCutPoints(double m1, double s1, double m2, double s2, out double x1, out double x2) {
+      double a = (s1 * s1 - s2 * s2);
+      x1 = -(-m2 * s1 * s1 + m1 * s2 * s2 + Math.Sqrt(s1 * s1 * s2 * s2 * ((m1 - m2) * (m1 - m2) + 2.0 * (-s1 * s1 + s2 * s2) * Math.Log(s2 / s1)))) / a;
+      x2 = (m2 * s1 * s1 - m1 * s2 * s2 + Math.Sqrt(s1 * s1 * s2 * s2 * ((m1 - m2) * (m1 - m2) + 2.0 * (-s1 * s1 + s2 * s2) * Math.Log(s2 / s1)))) / a;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/ThresholdCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/ThresholdCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/ThresholdCalculator.cs	(revision 7570)
@@ -0,0 +1,47 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Base class for threshold calculators for discriminant function classification models.
+  /// </summary>
+  [StorableClass]
+  public abstract class ThresholdCalculator : NamedItem, IDiscriminantFunctionThresholdCalculator {
+
+    [StorableConstructor]
+    protected ThresholdCalculator(bool deserializing) : base(deserializing) { }
+    protected ThresholdCalculator(ThresholdCalculator original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public ThresholdCalculator()
+      : base() {
+      this.name = ItemName;
+      this.description = ItemDescription;
+    }
+
+    public abstract void Calculate(IClassificationProblemData problemData, IEnumerable<double> estimatedValues, IEnumerable<double> targetClassValues, out double[] classValues, out double[] thresholds);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringProblem.cs	(revision 7570)
@@ -0,0 +1,46 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("Clustering Problem", "A general clustering problem.")]
+  [Creatable("Problems")]
+  public class ClusteringProblem : DataAnalysisProblem<IClusteringProblemData>, IClusteringProblem {
+    [StorableConstructor]
+    protected ClusteringProblem(bool deserializing) : base(deserializing) { }
+    protected ClusteringProblem(ClusteringProblem original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ClusteringProblem(this, cloner); }
+
+    public ClusteringProblem()
+      : base() {
+      ProblemData = new ClusteringProblemData();
+    }
+
+    public override void ImportProblemDataFromFile(string fileName) {
+      ClusteringProblemData problemData = ClusteringProblemData.ImportFromFile(fileName);
+      ProblemData = problemData;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringProblemData.cs	(revision 7570)
@@ -0,0 +1,108 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.IO;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("ClusteringProblemData", "Represents an item containing all data defining a clustering problem.")]
+  public sealed class ClusteringProblemData : DataAnalysisProblemData, IClusteringProblemData, IStorableContent {
+    public string Filename { get; set; }
+
+    #region default data
+    private static double[,] kozaF1 = new double[,] {
+          {2.017885919,	-1.449165046},
+          {1.30060506,	-1.344523885},
+          {1.147134798,	-1.317989331},
+          {0.877182504,	-1.266142284},
+          {0.852562452,	-1.261020794},
+          {0.431095788,	-1.158793317},
+          {0.112586002,	-1.050908405},
+          {0.04594507,	-1.021989402},
+          {0.042572879,	-1.020438113},
+          {-0.074027291,	-0.959859562},
+          {-0.109178553,	-0.938094706},
+          {-0.259721109,	-0.803635355},
+          {-0.272991057,	-0.387519561},
+          {-0.161978191,	-0.193611001},
+          {-0.102489983,	-0.114215349},
+          {-0.01469968,	-0.014918985},
+          {-0.008863365,	-0.008942626},
+          {0.026751057,	0.026054094},
+          {0.166922436,	0.14309643},
+          {0.176953808,	0.1504144},
+          {0.190233418,	0.159916534},
+          {0.199800708,	0.166635331},
+          {0.261502822,	0.207600348},
+          {0.30182879,	0.232370249},
+          {0.83763905,	0.468046718}
+    };
+    private static Dataset defaultDataset;
+    private static IEnumerable<string> defaultAllowedInputVariables;
+
+    static ClusteringProblemData() {
+      defaultDataset = new Dataset(new string[] { "y", "x" }, kozaF1);
+      defaultDataset.Name = "Fourth-order Polynomial Function Benchmark Dataset";
+      defaultDataset.Description = "f(x) = x^4 + x^3 + x^2 + x^1";
+      defaultAllowedInputVariables = new List<string>() { "x", "y" };
+    }
+    #endregion
+
+    [StorableConstructor]
+    private ClusteringProblemData(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+
+    private ClusteringProblemData(ClusteringProblemData original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ClusteringProblemData(this, cloner); }
+
+    public ClusteringProblemData()
+      : this(defaultDataset, defaultAllowedInputVariables) {
+    }
+
+    public ClusteringProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables)
+      : base(dataset, allowedInputVariables) {
+    }
+
+
+    #region Import from file
+    public static ClusteringProblemData ImportFromFile(string fileName) {
+      TableFileParser csvFileParser = new TableFileParser();
+      csvFileParser.Parse(fileName);
+
+      Dataset dataset = new Dataset(csvFileParser.VariableNames, csvFileParser.Values);
+      dataset.Name = Path.GetFileName(fileName);
+
+      ClusteringProblemData problemData = new ClusteringProblemData(dataset, dataset.DoubleVariables);
+      problemData.Name = "Data imported from " + Path.GetFileName(fileName);
+      return problemData;
+    }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Clustering/ClusteringSolution.cs	(revision 7570)
@@ -0,0 +1,85 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a clustering data analysis solution
+  /// </summary>
+  [StorableClass]
+  public class ClusteringSolution : DataAnalysisSolution, IClusteringSolution {
+
+    [StorableConstructor]
+    protected ClusteringSolution(bool deserializing) : base(deserializing) { }
+    protected ClusteringSolution(ClusteringSolution original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public ClusteringSolution(IClusteringModel model, IClusteringProblemData problemData)
+      : base(model, problemData) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ClusteringSolution(this, cloner);
+    }
+
+    protected override void RecalculateResults() {
+    }
+
+    #region IClusteringSolution Members
+
+    public new IClusteringModel Model {
+      get { return (IClusteringModel)base.Model; }
+      set { base.Model = value; }
+    }
+
+    public new IClusteringProblemData ProblemData {
+      get { return (IClusteringProblemData)base.ProblemData; }
+      set { base.ProblemData = value; }
+    }
+
+    public virtual IEnumerable<int> ClusterValues {
+      get {
+        return GetClusterValues(Enumerable.Range(0, ProblemData.Dataset.Rows));
+      }
+    }
+
+    public virtual IEnumerable<int> TrainingClusterValues {
+      get {
+        return GetClusterValues(ProblemData.TrainingIndizes);
+      }
+    }
+
+    public virtual IEnumerable<int> TestClusterValues {
+      get {
+        return GetClusterValues(ProblemData.TestIndizes);
+      }
+    }
+
+    public virtual IEnumerable<int> GetClusterValues(IEnumerable<int> rows) {
+      return Model.GetClusterValues(ProblemData.Dataset, rows);
+    }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblem.cs	(revision 7570)
@@ -0,0 +1,95 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  public abstract class DataAnalysisProblem<T> : Problem,
+    IDataAnalysisProblem<T>
+    where T : class, IDataAnalysisProblemData {
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string ProblemDataParameterDescription = "The data set, target variable and input variables of the data analysis problem.";
+    #region parameter properties
+    IParameter IDataAnalysisProblem.ProblemDataParameter {
+      get { return ProblemDataParameter; }
+    }
+    public IValueParameter<T> ProblemDataParameter {
+      get { return (IValueParameter<T>)Parameters[ProblemDataParameterName]; }
+    }
+    #endregion
+    #region properties
+    IDataAnalysisProblemData IDataAnalysisProblem.ProblemData {
+      get { return ProblemData; }
+    }
+    public T ProblemData {
+      get { return ProblemDataParameter.Value; }
+      protected set {
+        ProblemDataParameter.Value = value;
+      }
+    }
+    #endregion
+    protected DataAnalysisProblem(DataAnalysisProblem<T> original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+    [StorableConstructor]
+    protected DataAnalysisProblem(bool deserializing) : base(deserializing) { }
+    public DataAnalysisProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<T>(ProblemDataParameterName, ProblemDataParameterDescription));
+      RegisterEventHandlers();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      ProblemDataParameter.ValueChanged += new EventHandler(ProblemDataParameter_ValueChanged);
+      if (ProblemDataParameter.Value != null) ProblemDataParameter.Value.Changed += new EventHandler(ProblemData_Changed);
+    }
+
+    private void ProblemDataParameter_ValueChanged(object sender, EventArgs e) {
+      ProblemDataParameter.Value.Changed += new EventHandler(ProblemData_Changed);
+      OnProblemDataChanged();
+      OnReset();
+    }
+
+    private void ProblemData_Changed(object sender, EventArgs e) {
+      OnReset();
+    }
+
+    public event EventHandler ProblemDataChanged;
+    protected virtual void OnProblemDataChanged() {
+      var handler = ProblemDataChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public abstract void ImportProblemDataFromFile(string fileName);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 7570)
@@ -0,0 +1,160 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  public abstract class DataAnalysisProblemData : ParameterizedNamedItem, IDataAnalysisProblemData {
+    protected const string DatasetParameterName = "Dataset";
+    protected const string InputVariablesParameterName = "InputVariables";
+    protected const string TrainingPartitionParameterName = "TrainingPartition";
+    protected const string TestPartitionParameterName = "TestPartition";
+
+    #region parameter properites
+    public IFixedValueParameter<Dataset> DatasetParameter {
+      get { return (IFixedValueParameter<Dataset>)Parameters[DatasetParameterName]; }
+    }
+    public IFixedValueParameter<ReadOnlyCheckedItemList<StringValue>> InputVariablesParameter {
+      get { return (IFixedValueParameter<ReadOnlyCheckedItemList<StringValue>>)Parameters[InputVariablesParameterName]; }
+    }
+    public IFixedValueParameter<IntRange> TrainingPartitionParameter {
+      get { return (IFixedValueParameter<IntRange>)Parameters[TrainingPartitionParameterName]; }
+    }
+    public IFixedValueParameter<IntRange> TestPartitionParameter {
+      get { return (IFixedValueParameter<IntRange>)Parameters[TestPartitionParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    protected bool isEmpty = false;
+    public bool IsEmpty {
+      get { return isEmpty; }
+    }
+    public Dataset Dataset {
+      get { return DatasetParameter.Value; }
+    }
+    public ICheckedItemList<StringValue> InputVariables {
+      get { return InputVariablesParameter.Value; }
+    }
+    public IEnumerable<string> AllowedInputVariables {
+      get { return InputVariables.CheckedItems.Select(x => x.Value.Value); }
+    }
+
+    public IntRange TrainingPartition {
+      get { return TrainingPartitionParameter.Value; }
+    }
+    public IntRange TestPartition {
+      get { return TestPartitionParameter.Value; }
+    }
+
+    public virtual IEnumerable<int> TrainingIndizes {
+      get {
+        return Enumerable.Range(TrainingPartition.Start, Math.Max(0, TrainingPartition.End - TrainingPartition.Start))
+                         .Where(IsTrainingSample);
+      }
+    }
+    public virtual IEnumerable<int> TestIndizes {
+      get {
+        return Enumerable.Range(TestPartition.Start, Math.Max(0, TestPartition.End - TestPartition.Start))
+           .Where(IsTestSample);
+      }
+    }
+
+    public virtual bool IsTrainingSample(int index) {
+      return index >= 0 && index < Dataset.Rows &&
+        TrainingPartition.Start <= index && index < TrainingPartition.End &&
+        (index < TestPartition.Start || TestPartition.End <= index);
+    }
+
+    public virtual bool IsTestSample(int index) {
+      return index >= 0 && index < Dataset.Rows &&
+             TestPartition.Start <= index && index < TestPartition.End;
+    }
+    #endregion
+
+    protected DataAnalysisProblemData(DataAnalysisProblemData original, Cloner cloner)
+      : base(original, cloner) {
+      isEmpty = original.isEmpty;
+      RegisterEventHandlers();
+    }
+    [StorableConstructor]
+    protected DataAnalysisProblemData(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    protected DataAnalysisProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables) {
+      if (dataset == null) throw new ArgumentNullException("The dataset must not be null.");
+      if (allowedInputVariables == null) throw new ArgumentNullException("The allowedInputVariables must not be null.");
+
+      if (allowedInputVariables.Except(dataset.DoubleVariables).Any())
+        throw new ArgumentException("All allowed input variables must be present in the dataset and of type double.");
+
+      var inputVariables = new CheckedItemList<StringValue>(dataset.DoubleVariables.Select(x => new StringValue(x)));
+      foreach (StringValue x in inputVariables)
+        inputVariables.SetItemCheckedState(x, allowedInputVariables.Contains(x.Value));
+
+      int trainingPartitionStart = 0;
+      int trainingPartitionEnd = dataset.Rows / 2;
+      int testPartitionStart = dataset.Rows / 2;
+      int testPartitionEnd = dataset.Rows;
+
+      Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", dataset));
+      Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>(InputVariablesParameterName, "", inputVariables.AsReadOnly()));
+      Parameters.Add(new FixedValueParameter<IntRange>(TrainingPartitionParameterName, "", new IntRange(trainingPartitionStart, trainingPartitionEnd)));
+      Parameters.Add(new FixedValueParameter<IntRange>(TestPartitionParameterName, "", new IntRange(testPartitionStart, testPartitionEnd)));
+
+      ((ValueParameter<Dataset>)DatasetParameter).ReactOnValueToStringChangedAndValueItemImageChanged = false;
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      DatasetParameter.ValueChanged += new EventHandler(Parameter_ValueChanged);
+      InputVariables.CheckedItemsChanged += new CollectionItemsChangedEventHandler<IndexedItem<StringValue>>(InputVariables_CheckedItemsChanged);
+      TrainingPartition.ValueChanged += new EventHandler(Parameter_ValueChanged);
+      TestPartition.ValueChanged += new EventHandler(Parameter_ValueChanged);
+    }
+
+    private void InputVariables_CheckedItemsChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<StringValue>> e) {
+      OnChanged();
+    }
+
+    private void Parameter_ValueChanged(object sender, EventArgs e) {
+      OnChanged();
+    }
+
+    public event EventHandler Changed;
+    protected virtual void OnChanged() {
+      var listeners = Changed;
+      if (listeners != null) listeners(this, EventArgs.Empty);
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisSolution.cs	(revision 7570)
@@ -0,0 +1,168 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Abstract base class for data analysis solutions
+  /// </summary>
+  [StorableClass]
+  public abstract class DataAnalysisSolution : ResultCollection, IDataAnalysisSolution {
+    private const string ModelResultName = "Model";
+    private const string ProblemDataResultName = "ProblemData";
+
+    public string Filename { get; set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Function; }
+    }
+
+    #region properties
+    public IDataAnalysisModel Model {
+      get { return (IDataAnalysisModel)this[ModelResultName].Value; }
+      protected set {
+        if (this[ModelResultName].Value != value) {
+          if (value != null) {
+            this[ModelResultName].Value = value;
+            OnModelChanged();
+          }
+        }
+      }
+    }
+
+    public IDataAnalysisProblemData ProblemData {
+      get { return (IDataAnalysisProblemData)this[ProblemDataResultName].Value; }
+      set {
+        if (this[ProblemDataResultName].Value != value) {
+          if (value != null) {
+            ProblemData.Changed -= new EventHandler(ProblemData_Changed);
+            this[ProblemDataResultName].Value = value;
+            ProblemData.Changed += new EventHandler(ProblemData_Changed);
+            OnProblemDataChanged();
+          }
+        }
+      }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected DataAnalysisSolution(bool deserializing) : base(deserializing) { }
+    protected DataAnalysisSolution(DataAnalysisSolution original, Cloner cloner)
+      : base(original, cloner) {
+      name = original.Name;
+      description = original.Description;
+    }
+    public DataAnalysisSolution(IDataAnalysisModel model, IDataAnalysisProblemData problemData)
+      : base() {
+      name = ItemName;
+      description = ItemDescription;
+      Add(new Result(ModelResultName, "The data analysis model.", model));
+      Add(new Result(ProblemDataResultName, "The data analysis problem data.", problemData));
+
+      problemData.Changed += new EventHandler(ProblemData_Changed);
+    }
+
+    protected abstract void RecalculateResults();
+
+    private void ProblemData_Changed(object sender, EventArgs e) {
+      OnProblemDataChanged();
+    }
+
+    public event EventHandler ModelChanged;
+    protected virtual void OnModelChanged() {
+      RecalculateResults();
+      var listeners = ModelChanged;
+      if (listeners != null) listeners(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ProblemDataChanged;
+    protected virtual void OnProblemDataChanged() {
+      RecalculateResults();
+      var listeners = ProblemDataChanged;
+      if (listeners != null) listeners(this, EventArgs.Empty);
+    }
+
+    #region INamedItem Members
+    [Storable]
+    protected string name;
+    public string Name {
+      get { return name; }
+      set {
+        if (!CanChangeName) throw new NotSupportedException("Name cannot be changed.");
+        if (!(name.Equals(value) || (value == null) && (name == string.Empty))) {
+          CancelEventArgs<string> e = value == null ? new CancelEventArgs<string>(string.Empty) : new CancelEventArgs<string>(value);
+          OnNameChanging(e);
+          if (!e.Cancel) {
+            name = value == null ? string.Empty : value;
+            OnNameChanged();
+          }
+        }
+      }
+    }
+    public virtual bool CanChangeName {
+      get { return true; }
+    }
+    [Storable]
+    protected string description;
+    public string Description {
+      get { return description; }
+      set {
+        if (!CanChangeDescription) throw new NotSupportedException("Description cannot be changed.");
+        if (!(description.Equals(value) || (value == null) && (description == string.Empty))) {
+          description = value == null ? string.Empty : value;
+          OnDescriptionChanged();
+        }
+      }
+    }
+    public virtual bool CanChangeDescription {
+      get { return true; }
+    }
+
+    public override string ToString() {
+      return Name;
+    }
+
+    public event EventHandler<CancelEventArgs<string>> NameChanging;
+    protected virtual void OnNameChanging(CancelEventArgs<string> e) {
+      var handler = NameChanging;
+      if (handler != null) handler(this, e);
+    }
+
+    public event EventHandler NameChanged;
+    protected virtual void OnNameChanged() {
+      var handler = NameChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+      OnToStringChanged();
+    }
+
+    public event EventHandler DescriptionChanged;
+    protected virtual void OnDescriptionChanged() {
+      var handler = DescriptionChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionModel.cs	(revision 7570)
@@ -0,0 +1,60 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [Item("Constant Regression Model", "A model that always returns the same constant value regardless of the presented input data.")]
+  public class ConstantRegressionModel : NamedItem, IRegressionModel {
+    [Storable]
+    private double constant;
+    public double Constant {
+      get { return constant; }
+    }
+
+    [StorableConstructor]
+    protected ConstantRegressionModel(bool deserializing) : base(deserializing) { }
+    protected ConstantRegressionModel(ConstantRegressionModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.constant = original.constant;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new ConstantRegressionModel(this, cloner); }
+
+    public ConstantRegressionModel(double constant)
+      : base() {
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.constant = constant;
+    }
+
+    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+      return rows.Select(row => Constant);
+    }
+
+    public IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new ConstantRegressionSolution(this, problemData);
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/ConstantRegressionSolution.cs	(revision 7570)
@@ -0,0 +1,26 @@
+﻿using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item(Name = "Constant Regression Solution", Description = "Represents a constant regression solution (model + data).")]
+  public class ConstantRegressionSolution : RegressionSolution {
+    public new ConstantRegressionModel Model {
+      get { return (ConstantRegressionModel)base.Model; }
+      set { base.Model = value; }
+    }
+
+    [StorableConstructor]
+    protected ConstantRegressionSolution(bool deserializing) : base(deserializing) { }
+    protected ConstantRegressionSolution(ConstantRegressionSolution original, Cloner cloner) : base(original, cloner) { }
+    public ConstantRegressionSolution(ConstantRegressionModel model, IRegressionProblemData problemData)
+      : base(model, problemData) {
+      RecalculateResults();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ConstantRegressionSolution(this, cloner);
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleModel.cs	(revision 7570)
@@ -0,0 +1,112 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents regression solutions that contain an ensemble of multiple regression models
+  /// </summary>
+  [StorableClass]
+  [Item("RegressionEnsembleModel", "A regression model that contains an ensemble of multiple regression models")]
+  public class RegressionEnsembleModel : NamedItem, IRegressionEnsembleModel {
+
+    private List<IRegressionModel> models;
+    public IEnumerable<IRegressionModel> Models {
+      get { return new List<IRegressionModel>(models); }
+    }
+
+    [Storable(Name = "Models")]
+    private IEnumerable<IRegressionModel> StorableModels {
+      get { return models; }
+      set { models = value.ToList(); }
+    }
+
+    #region backwards compatiblity 3.3.5
+    [Storable(Name = "models", AllowOneWay = true)]
+    private List<IRegressionModel> OldStorableModels {
+      set { models = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected RegressionEnsembleModel(bool deserializing) : base(deserializing) { }
+    protected RegressionEnsembleModel(RegressionEnsembleModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.models = original.Models.Select(m => cloner.Clone(m)).ToList();
+    }
+
+    public RegressionEnsembleModel() : this(Enumerable.Empty<IRegressionModel>()) { }
+    public RegressionEnsembleModel(IEnumerable<IRegressionModel> models)
+      : base() {
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.models = new List<IRegressionModel>(models);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionEnsembleModel(this, cloner);
+    }
+
+    #region IRegressionEnsembleModel Members
+
+    public void Add(IRegressionModel model) {
+      models.Add(model);
+    }
+    public void Remove(IRegressionModel model) {
+      models.Remove(model);
+    }
+
+    public IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows) {
+      var estimatedValuesEnumerators = (from model in models
+                                        select model.GetEstimatedValues(dataset, rows).GetEnumerator())
+                                       .ToList();
+
+      while (estimatedValuesEnumerators.All(en => en.MoveNext())) {
+        yield return from enumerator in estimatedValuesEnumerators
+                     select enumerator.Current;
+      }
+    }
+
+    #endregion
+
+    #region IRegressionModel Members
+
+    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
+      foreach (var estimatedValuesVector in GetEstimatedValueVectors(dataset, rows)) {
+        yield return estimatedValuesVector.Average();
+      }
+    }
+
+    public RegressionEnsembleSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionEnsembleSolution(this.Models, problemData);
+    }
+    IRegressionSolution IRegressionModel.CreateRegressionSolution(IRegressionProblemData problemData) {
+      return CreateRegressionSolution(problemData);
+    }
+
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleProblemData.cs	(revision 7570)
@@ -0,0 +1,83 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("RegressionEnsembleProblemData", "Represents an item containing all data defining a regression problem.")]
+  public sealed class RegressionEnsembleProblemData : RegressionProblemData {
+
+    public override bool IsTrainingSample(int index) {
+      return index >= 0 && index < Dataset.Rows &&
+             TrainingPartition.Start <= index && index < TrainingPartition.End;
+    }
+
+    public override bool IsTestSample(int index) {
+      return index >= 0 && index < Dataset.Rows &&
+             TestPartition.Start <= index && index < TestPartition.End;
+    }
+
+    private static readonly RegressionEnsembleProblemData emptyProblemData;
+    public new static RegressionEnsembleProblemData EmptyProblemData {
+      get { return emptyProblemData; }
+    }
+    static RegressionEnsembleProblemData() {
+      var problemData = new RegressionEnsembleProblemData();
+      problemData.Parameters.Clear();
+      problemData.Name = "Empty Regression ProblemData";
+      problemData.Description = "This ProblemData acts as place holder before the correct problem data is loaded.";
+      problemData.isEmpty = true;
+
+      problemData.Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", new Dataset()));
+      problemData.Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>(InputVariablesParameterName, ""));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TrainingPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TestPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>()));
+      emptyProblemData = problemData;
+    }
+
+    [StorableConstructor]
+    private RegressionEnsembleProblemData(bool deserializing) : base(deserializing) { }
+    private RegressionEnsembleProblemData(RegressionEnsembleProblemData original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      if (this == emptyProblemData) return emptyProblemData;
+      return new RegressionEnsembleProblemData(this, cloner);
+    }
+
+    public RegressionEnsembleProblemData() : base() { }
+    public RegressionEnsembleProblemData(IRegressionProblemData regressionProblemData)
+      : base(regressionProblemData.Dataset, regressionProblemData.AllowedInputVariables, regressionProblemData.TargetVariable) {
+      TrainingPartition.Start = regressionProblemData.TrainingPartition.Start;
+      TrainingPartition.End = regressionProblemData.TrainingPartition.End;
+      TestPartition.Start = regressionProblemData.TestPartition.Start;
+      TestPartition.End = regressionProblemData.TestPartition.End;
+    }
+    public RegressionEnsembleProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable)
+      : base(dataset, allowedInputVariables, targetVariable) {
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionEnsembleSolution.cs	(revision 7570)
@@ -0,0 +1,282 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents regression solutions that contain an ensemble of multiple regression models
+  /// </summary>
+  [StorableClass]
+  [Item("Regression Ensemble Solution", "A regression solution that contains an ensemble of multiple regression models")]
+  [Creatable("Data Analysis - Ensembles")]
+  public sealed class RegressionEnsembleSolution : RegressionSolution, IRegressionEnsembleSolution {
+    public new IRegressionEnsembleModel Model {
+      get { return (IRegressionEnsembleModel)base.Model; }
+    }
+
+    public new RegressionEnsembleProblemData ProblemData {
+      get { return (RegressionEnsembleProblemData)base.ProblemData; }
+      set { base.ProblemData = value; }
+    }
+
+    private readonly ItemCollection<IRegressionSolution> regressionSolutions;
+    public IItemCollection<IRegressionSolution> RegressionSolutions {
+      get { return regressionSolutions; }
+    }
+
+    [Storable]
+    private Dictionary<IRegressionModel, IntRange> trainingPartitions;
+    [Storable]
+    private Dictionary<IRegressionModel, IntRange> testPartitions;
+
+    [StorableConstructor]
+    private RegressionEnsembleSolution(bool deserializing)
+      : base(deserializing) {
+      regressionSolutions = new ItemCollection<IRegressionSolution>();
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      foreach (var model in Model.Models) {
+        IRegressionProblemData problemData = (IRegressionProblemData)ProblemData.Clone();
+        problemData.TrainingPartition.Start = trainingPartitions[model].Start;
+        problemData.TrainingPartition.End = trainingPartitions[model].End;
+        problemData.TestPartition.Start = testPartitions[model].Start;
+        problemData.TestPartition.End = testPartitions[model].End;
+
+        regressionSolutions.Add(model.CreateRegressionSolution(problemData));
+      }
+      RegisterRegressionSolutionsEventHandler();
+    }
+
+    private RegressionEnsembleSolution(RegressionEnsembleSolution original, Cloner cloner)
+      : base(original, cloner) {
+      trainingPartitions = new Dictionary<IRegressionModel, IntRange>();
+      testPartitions = new Dictionary<IRegressionModel, IntRange>();
+      foreach (var pair in original.trainingPartitions) {
+        trainingPartitions[cloner.Clone(pair.Key)] = cloner.Clone(pair.Value);
+      }
+      foreach (var pair in original.testPartitions) {
+        testPartitions[cloner.Clone(pair.Key)] = cloner.Clone(pair.Value);
+      }
+
+      regressionSolutions = cloner.Clone(original.regressionSolutions);
+      RegisterRegressionSolutionsEventHandler();
+    }
+
+    public RegressionEnsembleSolution()
+      : base(new RegressionEnsembleModel(), RegressionEnsembleProblemData.EmptyProblemData) {
+      trainingPartitions = new Dictionary<IRegressionModel, IntRange>();
+      testPartitions = new Dictionary<IRegressionModel, IntRange>();
+      regressionSolutions = new ItemCollection<IRegressionSolution>();
+
+      RegisterRegressionSolutionsEventHandler();
+    }
+
+    public RegressionEnsembleSolution(IEnumerable<IRegressionModel> models, IRegressionProblemData problemData)
+      : this(models, problemData,
+             models.Select(m => (IntRange)problemData.TrainingPartition.Clone()),
+             models.Select(m => (IntRange)problemData.TestPartition.Clone())
+      ) { }
+
+    public RegressionEnsembleSolution(IEnumerable<IRegressionModel> models, IRegressionProblemData problemData, IEnumerable<IntRange> trainingPartitions, IEnumerable<IntRange> testPartitions)
+      : base(new RegressionEnsembleModel(Enumerable.Empty<IRegressionModel>()), new RegressionEnsembleProblemData(problemData)) {
+      this.trainingPartitions = new Dictionary<IRegressionModel, IntRange>();
+      this.testPartitions = new Dictionary<IRegressionModel, IntRange>();
+      this.regressionSolutions = new ItemCollection<IRegressionSolution>();
+
+      List<IRegressionSolution> solutions = new List<IRegressionSolution>();
+      var modelEnumerator = models.GetEnumerator();
+      var trainingPartitionEnumerator = trainingPartitions.GetEnumerator();
+      var testPartitionEnumerator = testPartitions.GetEnumerator();
+
+      while (modelEnumerator.MoveNext() & trainingPartitionEnumerator.MoveNext() & testPartitionEnumerator.MoveNext()) {
+        var p = (IRegressionProblemData)problemData.Clone();
+        p.TrainingPartition.Start = trainingPartitionEnumerator.Current.Start;
+        p.TrainingPartition.End = trainingPartitionEnumerator.Current.End;
+        p.TestPartition.Start = testPartitionEnumerator.Current.Start;
+        p.TestPartition.End = testPartitionEnumerator.Current.End;
+
+        solutions.Add(modelEnumerator.Current.CreateRegressionSolution(p));
+      }
+      if (modelEnumerator.MoveNext() | trainingPartitionEnumerator.MoveNext() | testPartitionEnumerator.MoveNext()) {
+        throw new ArgumentException();
+      }
+
+      RegisterRegressionSolutionsEventHandler();
+      regressionSolutions.AddRange(solutions);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RegressionEnsembleSolution(this, cloner);
+    }
+    private void RegisterRegressionSolutionsEventHandler() {
+      regressionSolutions.ItemsAdded += new CollectionItemsChangedEventHandler<IRegressionSolution>(regressionSolutions_ItemsAdded);
+      regressionSolutions.ItemsRemoved += new CollectionItemsChangedEventHandler<IRegressionSolution>(regressionSolutions_ItemsRemoved);
+      regressionSolutions.CollectionReset += new CollectionItemsChangedEventHandler<IRegressionSolution>(regressionSolutions_CollectionReset);
+    }
+
+    protected override void RecalculateResults() {
+      CalculateResults();
+    }
+
+    #region Evaluation
+    public override IEnumerable<double> EstimatedTrainingValues {
+      get {
+        var rows = ProblemData.TrainingIndizes;
+        var estimatedValuesEnumerators = (from model in Model.Models
+                                          select new { Model = model, EstimatedValuesEnumerator = model.GetEstimatedValues(ProblemData.Dataset, rows).GetEnumerator() })
+                                         .ToList();
+        var rowsEnumerator = rows.GetEnumerator();
+        // aggregate to make sure that MoveNext is called for all enumerators 
+        while (rowsEnumerator.MoveNext() & estimatedValuesEnumerators.Select(en => en.EstimatedValuesEnumerator.MoveNext()).Aggregate(true, (acc, b) => acc & b)) {
+          int currentRow = rowsEnumerator.Current;
+
+          var selectedEnumerators = from pair in estimatedValuesEnumerators
+                                    where RowIsTrainingForModel(currentRow, pair.Model) && !RowIsTestForModel(currentRow, pair.Model)
+                                    select pair.EstimatedValuesEnumerator;
+          yield return AggregateEstimatedValues(selectedEnumerators.Select(x => x.Current));
+        }
+      }
+    }
+
+    public override IEnumerable<double> EstimatedTestValues {
+      get {
+        var rows = ProblemData.TestIndizes;
+        var estimatedValuesEnumerators = (from model in Model.Models
+                                          select new { Model = model, EstimatedValuesEnumerator = model.GetEstimatedValues(ProblemData.Dataset, rows).GetEnumerator() })
+                                         .ToList();
+        var rowsEnumerator = ProblemData.TestIndizes.GetEnumerator();
+        // aggregate to make sure that MoveNext is called for all enumerators 
+        while (rowsEnumerator.MoveNext() & estimatedValuesEnumerators.Select(en => en.EstimatedValuesEnumerator.MoveNext()).Aggregate(true, (acc, b) => acc & b)) {
+          int currentRow = rowsEnumerator.Current;
+
+          var selectedEnumerators = from pair in estimatedValuesEnumerators
+                                    where RowIsTestForModel(currentRow, pair.Model)
+                                    select pair.EstimatedValuesEnumerator;
+
+          yield return AggregateEstimatedValues(selectedEnumerators.Select(x => x.Current));
+        }
+      }
+    }
+
+    private bool RowIsTrainingForModel(int currentRow, IRegressionModel model) {
+      return trainingPartitions == null || !trainingPartitions.ContainsKey(model) ||
+              (trainingPartitions[model].Start <= currentRow && currentRow < trainingPartitions[model].End);
+    }
+
+    private bool RowIsTestForModel(int currentRow, IRegressionModel model) {
+      return testPartitions == null || !testPartitions.ContainsKey(model) ||
+              (testPartitions[model].Start <= currentRow && currentRow < testPartitions[model].End);
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows) {
+      return from xs in GetEstimatedValueVectors(ProblemData.Dataset, rows)
+             select AggregateEstimatedValues(xs);
+    }
+
+    public IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows) {
+      if (!Model.Models.Any()) yield break;
+      var estimatedValuesEnumerators = (from model in Model.Models
+                                        select model.GetEstimatedValues(dataset, rows).GetEnumerator())
+                                       .ToList();
+
+      while (estimatedValuesEnumerators.All(en => en.MoveNext())) {
+        yield return from enumerator in estimatedValuesEnumerators
+                     select enumerator.Current;
+      }
+    }
+
+    private double AggregateEstimatedValues(IEnumerable<double> estimatedValues) {
+      return estimatedValues.DefaultIfEmpty(double.NaN).Average();
+    }
+    #endregion
+
+    protected override void OnProblemDataChanged() {
+      IRegressionProblemData problemData = new RegressionProblemData(ProblemData.Dataset,
+                                                                     ProblemData.AllowedInputVariables,
+                                                                     ProblemData.TargetVariable);
+      problemData.TrainingPartition.Start = ProblemData.TrainingPartition.Start;
+      problemData.TrainingPartition.End = ProblemData.TrainingPartition.End;
+      problemData.TestPartition.Start = ProblemData.TestPartition.Start;
+      problemData.TestPartition.End = ProblemData.TestPartition.End;
+
+      foreach (var solution in RegressionSolutions) {
+        if (solution is RegressionEnsembleSolution)
+          solution.ProblemData = ProblemData;
+        else
+          solution.ProblemData = problemData;
+      }
+      foreach (var trainingPartition in trainingPartitions.Values) {
+        trainingPartition.Start = ProblemData.TrainingPartition.Start;
+        trainingPartition.End = ProblemData.TrainingPartition.End;
+      }
+      foreach (var testPartition in testPartitions.Values) {
+        testPartition.Start = ProblemData.TestPartition.Start;
+        testPartition.End = ProblemData.TestPartition.End;
+      }
+
+      base.OnProblemDataChanged();
+    }
+
+    public void AddRegressionSolutions(IEnumerable<IRegressionSolution> solutions) {
+      regressionSolutions.AddRange(solutions);
+    }
+    public void RemoveRegressionSolutions(IEnumerable<IRegressionSolution> solutions) {
+      regressionSolutions.RemoveRange(solutions);
+    }
+
+    private void regressionSolutions_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRegressionSolution> e) {
+      foreach (var solution in e.Items) AddRegressionSolution(solution);
+      RecalculateResults();
+    }
+    private void regressionSolutions_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRegressionSolution> e) {
+      foreach (var solution in e.Items) RemoveRegressionSolution(solution);
+      RecalculateResults();
+    }
+    private void regressionSolutions_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRegressionSolution> e) {
+      foreach (var solution in e.OldItems) RemoveRegressionSolution(solution);
+      foreach (var solution in e.Items) AddRegressionSolution(solution);
+      RecalculateResults();
+    }
+
+    private void AddRegressionSolution(IRegressionSolution solution) {
+      if (Model.Models.Contains(solution.Model)) throw new ArgumentException();
+      Model.Add(solution.Model);
+      trainingPartitions[solution.Model] = solution.ProblemData.TrainingPartition;
+      testPartitions[solution.Model] = solution.ProblemData.TestPartition;
+    }
+
+    private void RemoveRegressionSolution(IRegressionSolution solution) {
+      if (!Model.Models.Contains(solution.Model)) throw new ArgumentException();
+      Model.Remove(solution.Model);
+      trainingPartitions.Remove(solution.Model);
+      testPartitions.Remove(solution.Model);
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblem.cs	(revision 7570)
@@ -0,0 +1,48 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("Regression Problem", "A general regression problem.")]
+  [Creatable("Problems")]
+  public class RegressionProblem : DataAnalysisProblem<IRegressionProblemData>, IRegressionProblem, IStorableContent {
+    public string Filename { get; set; }
+
+    [StorableConstructor]
+    protected RegressionProblem(bool deserializing) : base(deserializing) { }
+    protected RegressionProblem(RegressionProblem original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new RegressionProblem(this, cloner); }
+
+    public RegressionProblem()
+      : base() {
+      ProblemData = new RegressionProblemData();
+    }
+
+    public override void ImportProblemDataFromFile(string fileName) {
+      RegressionProblemData problemData = RegressionProblemData.ImportFromFile(fileName);
+      ProblemData = problemData;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionProblemData.cs	(revision 7570)
@@ -0,0 +1,153 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.IO;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("RegressionProblemData", "Represents an item containing all data defining a regression problem.")]
+  public class RegressionProblemData : DataAnalysisProblemData, IRegressionProblemData, IStorableContent {
+    protected const string TargetVariableParameterName = "TargetVariable";
+    public string Filename { get; set; }
+
+    #region default data
+    private static double[,] kozaF1 = new double[,] {
+          {2.017885919,	-1.449165046},
+          {1.30060506,	-1.344523885},
+          {1.147134798,	-1.317989331},
+          {0.877182504,	-1.266142284},
+          {0.852562452,	-1.261020794},
+          {0.431095788,	-1.158793317},
+          {0.112586002,	-1.050908405},
+          {0.04594507,	-1.021989402},
+          {0.042572879,	-1.020438113},
+          {-0.074027291,	-0.959859562},
+          {-0.109178553,	-0.938094706},
+          {-0.259721109,	-0.803635355},
+          {-0.272991057,	-0.387519561},
+          {-0.161978191,	-0.193611001},
+          {-0.102489983,	-0.114215349},
+          {-0.01469968,	-0.014918985},
+          {-0.008863365,	-0.008942626},
+          {0.026751057,	0.026054094},
+          {0.166922436,	0.14309643},
+          {0.176953808,	0.1504144},
+          {0.190233418,	0.159916534},
+          {0.199800708,	0.166635331},
+          {0.261502822,	0.207600348},
+          {0.30182879,	0.232370249},
+          {0.83763905,	0.468046718}
+    };
+    private static readonly Dataset defaultDataset;
+    private static readonly IEnumerable<string> defaultAllowedInputVariables;
+    private static readonly string defaultTargetVariable;
+
+    private static readonly RegressionProblemData emptyProblemData;
+    public static RegressionProblemData EmptyProblemData {
+      get { return emptyProblemData; }
+    }
+
+    static RegressionProblemData() {
+      defaultDataset = new Dataset(new string[] { "y", "x" }, kozaF1);
+      defaultDataset.Name = "Fourth-order Polynomial Function Benchmark Dataset";
+      defaultDataset.Description = "f(x) = x^4 + x^3 + x^2 + x^1";
+      defaultAllowedInputVariables = new List<string>() { "x" };
+      defaultTargetVariable = "y";
+
+      var problemData = new RegressionProblemData();
+      problemData.Parameters.Clear();
+      problemData.Name = "Empty Regression ProblemData";
+      problemData.Description = "This ProblemData acts as place holder before the correct problem data is loaded.";
+      problemData.isEmpty = true;
+
+      problemData.Parameters.Add(new FixedValueParameter<Dataset>(DatasetParameterName, "", new Dataset()));
+      problemData.Parameters.Add(new FixedValueParameter<ReadOnlyCheckedItemList<StringValue>>(InputVariablesParameterName, ""));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TrainingPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new FixedValueParameter<IntRange>(TestPartitionParameterName, "", (IntRange)new IntRange(0, 0).AsReadOnly()));
+      problemData.Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>()));
+      emptyProblemData = problemData;
+    }
+    #endregion
+
+    public ConstrainedValueParameter<StringValue> TargetVariableParameter {
+      get { return (ConstrainedValueParameter<StringValue>)Parameters[TargetVariableParameterName]; }
+    }
+    public string TargetVariable {
+      get { return TargetVariableParameter.Value.Value; }
+    }
+
+    [StorableConstructor]
+    protected RegressionProblemData(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterParameterEvents();
+    }
+
+    protected RegressionProblemData(RegressionProblemData original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterParameterEvents();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      if (this == emptyProblemData) return emptyProblemData;
+      return new RegressionProblemData(this, cloner);
+    }
+
+    public RegressionProblemData()
+      : this(defaultDataset, defaultAllowedInputVariables, defaultTargetVariable) {
+    }
+
+    public RegressionProblemData(Dataset dataset, IEnumerable<string> allowedInputVariables, string targetVariable)
+      : base(dataset, allowedInputVariables) {
+      var variables = InputVariables.Select(x => x.AsReadOnly()).ToList();
+      Parameters.Add(new ConstrainedValueParameter<StringValue>(TargetVariableParameterName, new ItemSet<StringValue>(variables), variables.Where(x => x.Value == targetVariable).First()));
+      RegisterParameterEvents();
+    }
+
+    private void RegisterParameterEvents() {
+      TargetVariableParameter.ValueChanged += new EventHandler(TargetVariableParameter_ValueChanged);
+    }
+    private void TargetVariableParameter_ValueChanged(object sender, EventArgs e) {
+      OnChanged();
+    }
+
+    #region Import from file
+    public static RegressionProblemData ImportFromFile(string fileName) {
+      TableFileParser csvFileParser = new TableFileParser();
+      csvFileParser.Parse(fileName);
+
+      Dataset dataset = new Dataset(csvFileParser.VariableNames, csvFileParser.Values);
+      dataset.Name = Path.GetFileName(fileName);
+
+      RegressionProblemData problemData = new RegressionProblemData(dataset, dataset.DoubleVariables.Skip(1), dataset.DoubleVariables.First());
+      problemData.Name = "Data imported from " + Path.GetFileName(fileName);
+      return problemData;
+    }
+    #endregion
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs	(revision 7570)
@@ -0,0 +1,85 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  /// <summary>
+  /// Represents a regression data analysis solution
+  /// </summary>
+  [StorableClass]
+  public abstract class RegressionSolution : RegressionSolutionBase {
+    protected readonly Dictionary<int, double> evaluationCache;
+
+    [StorableConstructor]
+    protected RegressionSolution(bool deserializing)
+      : base(deserializing) {
+      evaluationCache = new Dictionary<int, double>();
+    }
+    protected RegressionSolution(RegressionSolution original, Cloner cloner)
+      : base(original, cloner) {
+      evaluationCache = new Dictionary<int, double>(original.evaluationCache);
+    }
+    protected RegressionSolution(IRegressionModel model, IRegressionProblemData problemData)
+      : base(model, problemData) {
+      evaluationCache = new Dictionary<int, double>();
+    }
+
+    protected override void RecalculateResults() {
+      CalculateResults();
+    }
+
+    public override IEnumerable<double> EstimatedValues {
+      get { return GetEstimatedValues(Enumerable.Range(0, ProblemData.Dataset.Rows)); }
+    }
+    public override IEnumerable<double> EstimatedTrainingValues {
+      get { return GetEstimatedValues(ProblemData.TrainingIndizes); }
+    }
+    public override IEnumerable<double> EstimatedTestValues {
+      get { return GetEstimatedValues(ProblemData.TestIndizes); }
+    }
+
+    public override IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows) {
+      var rowsToEvaluate = rows.Except(evaluationCache.Keys);
+      var rowsEnumerator = rowsToEvaluate.GetEnumerator();
+      var valuesEnumerator = Model.GetEstimatedValues(ProblemData.Dataset, rowsToEvaluate).GetEnumerator();
+
+      while (rowsEnumerator.MoveNext() & valuesEnumerator.MoveNext()) {
+        evaluationCache.Add(rowsEnumerator.Current, valuesEnumerator.Current);
+      }
+
+      return rows.Select(row => evaluationCache[row]);
+    }
+
+    protected override void OnProblemDataChanged() {
+      evaluationCache.Clear();
+      base.OnProblemDataChanged();
+    }
+
+    protected override void OnModelChanged() {
+      evaluationCache.Clear();
+      base.OnModelChanged();
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionBase.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionBase.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionBase.cs	(revision 7570)
@@ -0,0 +1,205 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  public abstract class RegressionSolutionBase : DataAnalysisSolution, IRegressionSolution {
+    private const string TrainingMeanSquaredErrorResultName = "Mean squared error (training)";
+    private const string TestMeanSquaredErrorResultName = "Mean squared error (test)";
+    private const string TrainingMeanAbsoluteErrorResultName = "Mean absolute error (training)";
+    private const string TestMeanAbsoluteErrorResultName = "Mean absolute error (test)";
+    private const string TrainingSquaredCorrelationResultName = "Pearson's R² (training)";
+    private const string TestSquaredCorrelationResultName = "Pearson's R² (test)";
+    private const string TrainingRelativeErrorResultName = "Average relative error (training)";
+    private const string TestRelativeErrorResultName = "Average relative error (test)";
+    private const string TrainingNormalizedMeanSquaredErrorResultName = "Normalized mean squared error (training)";
+    private const string TestNormalizedMeanSquaredErrorResultName = "Normalized mean squared error (test)";
+    private const string TrainingMeanErrorResultName = "Mean error (training)";
+    private const string TestMeanErrorResultName = "Mean error (test)";
+
+    public new IRegressionModel Model {
+      get { return (IRegressionModel)base.Model; }
+      protected set { base.Model = value; }
+    }
+
+    public new IRegressionProblemData ProblemData {
+      get { return (IRegressionProblemData)base.ProblemData; }
+      set { base.ProblemData = value; }
+    }
+
+    public abstract IEnumerable<double> EstimatedValues { get; }
+    public abstract IEnumerable<double> EstimatedTrainingValues { get; }
+    public abstract IEnumerable<double> EstimatedTestValues { get; }
+    public abstract IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows);
+
+    #region Results
+    public double TrainingMeanSquaredError {
+      get { return ((DoubleValue)this[TrainingMeanSquaredErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingMeanSquaredErrorResultName].Value).Value = value; }
+    }
+    public double TestMeanSquaredError {
+      get { return ((DoubleValue)this[TestMeanSquaredErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestMeanSquaredErrorResultName].Value).Value = value; }
+    }
+    public double TrainingMeanAbsoluteError {
+      get { return ((DoubleValue)this[TrainingMeanAbsoluteErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingMeanAbsoluteErrorResultName].Value).Value = value; }
+    }
+    public double TestMeanAbsoluteError {
+      get { return ((DoubleValue)this[TestMeanAbsoluteErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestMeanAbsoluteErrorResultName].Value).Value = value; }
+    }
+    public double TrainingRSquared {
+      get { return ((DoubleValue)this[TrainingSquaredCorrelationResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingSquaredCorrelationResultName].Value).Value = value; }
+    }
+    public double TestRSquared {
+      get { return ((DoubleValue)this[TestSquaredCorrelationResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestSquaredCorrelationResultName].Value).Value = value; }
+    }
+    public double TrainingRelativeError {
+      get { return ((DoubleValue)this[TrainingRelativeErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingRelativeErrorResultName].Value).Value = value; }
+    }
+    public double TestRelativeError {
+      get { return ((DoubleValue)this[TestRelativeErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestRelativeErrorResultName].Value).Value = value; }
+    }
+    public double TrainingNormalizedMeanSquaredError {
+      get { return ((DoubleValue)this[TrainingNormalizedMeanSquaredErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingNormalizedMeanSquaredErrorResultName].Value).Value = value; }
+    }
+    public double TestNormalizedMeanSquaredError {
+      get { return ((DoubleValue)this[TestNormalizedMeanSquaredErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestNormalizedMeanSquaredErrorResultName].Value).Value = value; }
+    }
+    public double TrainingMeanError {
+      get { return ((DoubleValue)this[TrainingMeanErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TrainingMeanErrorResultName].Value).Value = value; }
+    }
+    public double TestMeanError {
+      get { return ((DoubleValue)this[TestMeanErrorResultName].Value).Value; }
+      private set { ((DoubleValue)this[TestMeanErrorResultName].Value).Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected RegressionSolutionBase(bool deserializing) : base(deserializing) { }
+    protected RegressionSolutionBase(RegressionSolutionBase original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    protected RegressionSolutionBase(IRegressionModel model, IRegressionProblemData problemData)
+      : base(model, problemData) {
+      Add(new Result(TrainingMeanSquaredErrorResultName, "Mean of squared errors of the model on the training partition", new DoubleValue()));
+      Add(new Result(TestMeanSquaredErrorResultName, "Mean of squared errors of the model on the test partition", new DoubleValue()));
+      Add(new Result(TrainingMeanAbsoluteErrorResultName, "Mean of absolute errors of the model on the training partition", new DoubleValue()));
+      Add(new Result(TestMeanAbsoluteErrorResultName, "Mean of absolute errors of the model on the test partition", new DoubleValue()));
+      Add(new Result(TrainingSquaredCorrelationResultName, "Squared Pearson's correlation coefficient of the model output and the actual values on the training partition", new DoubleValue()));
+      Add(new Result(TestSquaredCorrelationResultName, "Squared Pearson's correlation coefficient of the model output and the actual values on the test partition", new DoubleValue()));
+      Add(new Result(TrainingRelativeErrorResultName, "Average of the relative errors of the model output and the actual values on the training partition", new PercentValue()));
+      Add(new Result(TestRelativeErrorResultName, "Average of the relative errors of the model output and the actual values on the test partition", new PercentValue()));
+      Add(new Result(TrainingNormalizedMeanSquaredErrorResultName, "Normalized mean of squared errors of the model on the training partition", new DoubleValue()));
+      Add(new Result(TestNormalizedMeanSquaredErrorResultName, "Normalized mean of squared errors of the model on the test partition", new DoubleValue()));
+      Add(new Result(TrainingMeanErrorResultName, "Mean of errors of the model on the training partition", new DoubleValue()));
+      Add(new Result(TestMeanErrorResultName, "Mean of errors of the model on the test partition", new DoubleValue()));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.4
+
+      #region Backwards compatible code, remove with 3.5
+
+      if (!ContainsKey(TrainingMeanAbsoluteErrorResultName)) {
+        OnlineCalculatorError errorState;
+        Add(new Result(TrainingMeanAbsoluteErrorResultName, "Mean of absolute errors of the model on the training partition", new DoubleValue()));
+        double trainingMAE = OnlineMeanAbsoluteErrorCalculator.Calculate(EstimatedTrainingValues, ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes), out errorState);
+        TrainingMeanAbsoluteError = errorState == OnlineCalculatorError.None ? trainingMAE : double.NaN;
+      }
+
+      if (!ContainsKey(TestMeanAbsoluteErrorResultName)) {
+        OnlineCalculatorError errorState;
+        Add(new Result(TestMeanAbsoluteErrorResultName, "Mean of absolute errors of the model on the test partition", new DoubleValue()));
+        double testMAE = OnlineMeanAbsoluteErrorCalculator.Calculate(EstimatedTestValues, ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TestIndizes), out errorState);
+        TestMeanAbsoluteError = errorState == OnlineCalculatorError.None ? testMAE : double.NaN;
+      }
+
+      if (!ContainsKey(TrainingMeanErrorResultName)) {
+        OnlineCalculatorError errorState;
+        Add(new Result(TrainingMeanErrorResultName, "Mean of errors of the model on the training partition", new DoubleValue()));
+        double trainingME = OnlineMeanErrorCalculator.Calculate(EstimatedTrainingValues, ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes), out errorState);
+        TrainingMeanError = errorState == OnlineCalculatorError.None ? trainingME : double.NaN;
+      }
+      if (!ContainsKey(TestMeanErrorResultName)) {
+        OnlineCalculatorError errorState;
+        Add(new Result(TestMeanErrorResultName, "Mean of errors of the model on the test partition", new DoubleValue()));
+        double testME = OnlineMeanErrorCalculator.Calculate(EstimatedTestValues, ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TestIndizes), out errorState);
+        TestMeanError = errorState == OnlineCalculatorError.None ? testME : double.NaN;
+      }
+      #endregion
+    }
+
+    protected void CalculateResults() {
+      double[] estimatedTrainingValues = EstimatedTrainingValues.ToArray(); // cache values
+      double[] originalTrainingValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes).ToArray();
+      double[] estimatedTestValues = EstimatedTestValues.ToArray(); // cache values
+      double[] originalTestValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TestIndizes).ToArray();
+
+      OnlineCalculatorError errorState;
+      double trainingMSE = OnlineMeanSquaredErrorCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingMeanSquaredError = errorState == OnlineCalculatorError.None ? trainingMSE : double.NaN;
+      double testMSE = OnlineMeanSquaredErrorCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestMeanSquaredError = errorState == OnlineCalculatorError.None ? testMSE : double.NaN;
+
+      double trainingMAE = OnlineMeanAbsoluteErrorCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingMeanAbsoluteError = errorState == OnlineCalculatorError.None ? trainingMAE : double.NaN;
+      double testMAE = OnlineMeanAbsoluteErrorCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestMeanAbsoluteError = errorState == OnlineCalculatorError.None ? testMAE : double.NaN;
+
+      double trainingR2 = OnlinePearsonsRSquaredCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingRSquared = errorState == OnlineCalculatorError.None ? trainingR2 : double.NaN;
+      double testR2 = OnlinePearsonsRSquaredCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestRSquared = errorState == OnlineCalculatorError.None ? testR2 : double.NaN;
+
+      double trainingRelError = OnlineMeanAbsolutePercentageErrorCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingRelativeError = errorState == OnlineCalculatorError.None ? trainingRelError : double.NaN;
+      double testRelError = OnlineMeanAbsolutePercentageErrorCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestRelativeError = errorState == OnlineCalculatorError.None ? testRelError : double.NaN;
+
+      double trainingNMSE = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingNormalizedMeanSquaredError = errorState == OnlineCalculatorError.None ? trainingNMSE : double.NaN;
+      double testNMSE = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestNormalizedMeanSquaredError = errorState == OnlineCalculatorError.None ? testNMSE : double.NaN;
+
+      double trainingME = OnlineMeanErrorCalculator.Calculate(originalTrainingValues, estimatedTrainingValues, out errorState);
+      TrainingMeanError = errorState == OnlineCalculatorError.None ? trainingME : double.NaN;
+      double testME = OnlineMeanErrorCalculator.Calculate(originalTestValues, estimatedTestValues, out errorState);
+      TestMeanError = errorState == OnlineCalculatorError.None ? testME : double.NaN;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleModel.cs	(revision 7570)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClassificationEnsembleModel : IClassificationModel {
+    void Add(IClassificationModel model);
+    void Remove(IClassificationModel model);
+    IEnumerable<IClassificationModel> Models { get; }
+    IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationEnsembleSolution.cs	(revision 7570)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClassificationEnsembleSolution : IClassificationSolution {
+    new IClassificationEnsembleModel Model { get; }
+    IItemCollection<IClassificationSolution> ClassificationSolutions { get; }
+    IEnumerable<IEnumerable<double>> GetEstimatedClassValueVectors(Dataset dataset, IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationModel.cs	(revision 7570)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClassificationModel : IDataAnalysisModel {
+    IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows);
+    IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationProblem.cs	(revision 7570)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClassificationProblem : IDataAnalysisProblem<IClassificationProblemData> {
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationProblemData.cs	(revision 7570)
@@ -0,0 +1,40 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClassificationProblemData : IDataAnalysisProblemData {
+    string TargetVariable { get; }
+
+    IEnumerable<string> ClassNames { get; }
+    IEnumerable<double> ClassValues { get; }
+    int Classes { get; }
+
+    string GetClassName(double classValue);
+    double GetClassValue(string className);
+    void SetClassName(double classValue, string className);
+
+    double GetClassificationPenalty(string correctClass, string estimatedClass);
+    double GetClassificationPenalty(double correctClassValue, double estimatedClassValue);
+    void SetClassificationPenalty(string correctClassName, string estimatedClassName, double penalty);
+    void SetClassificationPenalty(double correctClassValue, double estimatedClassValue, double penalty);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IClassificationSolution.cs	(revision 7570)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClassificationSolution : IDataAnalysisSolution {
+    new IClassificationModel Model { get; }
+    new IClassificationProblemData ProblemData { get; set; }
+
+    IEnumerable<double> EstimatedClassValues { get; }
+    IEnumerable<double> EstimatedTrainingClassValues { get; }
+    IEnumerable<double> EstimatedTestClassValues { get; }
+    IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows);
+
+    double TrainingAccuracy { get; }
+    double TestAccuracy { get; }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs	(revision 7570)
@@ -0,0 +1,36 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDiscriminantFunctionClassificationModel : IClassificationModel {
+    IEnumerable<double> Thresholds { get; }
+    IEnumerable<double> ClassValues { get; }
+    // class values and thresholds can only be assigned simultanously
+    void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues);
+    IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows);
+
+    event EventHandler ThresholdsChanged;
+
+    IDiscriminantFunctionClassificationSolution CreateDiscriminantFunctionClassificationSolution(IClassificationProblemData problemData);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationSolution.cs	(revision 7570)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDiscriminantFunctionClassificationSolution : IClassificationSolution {
+    new IDiscriminantFunctionClassificationModel Model { get; }
+
+    IEnumerable<double> EstimatedValues { get; }
+    IEnumerable<double> EstimatedTrainingValues { get; }
+    IEnumerable<double> EstimatedTestValues { get; }
+    IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionThresholdCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionThresholdCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionThresholdCalculator.cs	(revision 7570)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDiscriminantFunctionThresholdCalculator : INamedItem {
+    void Calculate(IClassificationProblemData problemData, IEnumerable<double> estimatedValues, IEnumerable<double> targetClassValues, out double[] classValues, out double[] thresholds);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringModel.cs	(revision 7570)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClusteringModel : IDataAnalysisModel {
+    IEnumerable<int> GetClusterValues(Dataset dataset, IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringProblem.cs	(revision 7570)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClusteringProblem : IDataAnalysisProblem<IClusteringProblemData> {
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringProblemData.cs	(revision 7570)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClusteringProblemData : IDataAnalysisProblemData {
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Clustering/IClusteringSolution.cs	(revision 7570)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IClusteringSolution : IDataAnalysisSolution {
+    new IClusteringModel Model { get; }
+    new IClusteringProblemData ProblemData { get; set; }
+
+    IEnumerable<int> ClusterValues { get; }
+    IEnumerable<int> TrainingClusterValues { get; }
+    IEnumerable<int> TestClusterValues { get; }
+    IEnumerable<int> GetClusterValues(IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisModel.cs	(revision 7570)
@@ -0,0 +1,27 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDataAnalysisModel : INamedItem {
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblem.cs	(revision 7570)
@@ -0,0 +1,40 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDataAnalysisProblem : IProblem {
+    IParameter ProblemDataParameter { get; }
+    IDataAnalysisProblemData ProblemData { get; }
+    event EventHandler ProblemDataChanged;
+
+    void ImportProblemDataFromFile(string fileName);
+  }
+
+  public interface IDataAnalysisProblem<T> : IDataAnalysisProblem
+  where T : class, IDataAnalysisProblemData {
+    new IValueParameter<T> ProblemDataParameter { get; }
+    new T ProblemData { get; }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 7570)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDataAnalysisProblemData : INamedItem {
+    bool IsEmpty { get; }
+
+    Dataset Dataset { get; }
+    ICheckedItemList<StringValue> InputVariables { get; }
+    IEnumerable<string> AllowedInputVariables { get; }
+
+    IntRange TrainingPartition { get; }
+    IntRange TestPartition { get; }
+
+    IEnumerable<int> TrainingIndizes { get; }
+    IEnumerable<int> TestIndizes { get; }
+
+    bool IsTrainingSample(int index);
+    bool IsTestSample(int index);
+
+    event EventHandler Changed;
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisSolution.cs	(revision 7570)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IDataAnalysisSolution : INamedItem, IStorableContent {
+    IDataAnalysisModel Model { get; }
+    IDataAnalysisProblemData ProblemData { get; set; }
+
+    event EventHandler ModelChanged;
+    event EventHandler ProblemDataChanged;
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IOnlineCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IOnlineCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IOnlineCalculator.cs	(revision 7570)
@@ -0,0 +1,46 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  [Flags]
+  public enum OnlineCalculatorError { 
+    /// <summary>
+    /// No error occurred
+    /// </summary>
+    None = 0, 
+    /// <summary>
+    /// An invalid value has been added (often +/- Infinity and NaN are invalid values)
+    /// </summary>
+    InvalidValueAdded = 1, 
+    /// <summary>
+    /// The number of elements added to the evaluator is not sufficient to calculate the result value
+    /// </summary>
+    InsufficientElementsAdded = 2
+  }
+  public interface IOnlineCalculator {
+    OnlineCalculatorError ErrorState { get; }
+    double Value { get; }
+    void Reset();
+    void Add(double original, double estimated);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleModel.cs	(revision 7570)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IRegressionEnsembleModel : IRegressionModel {
+    void Add(IRegressionModel model);
+    void Remove(IRegressionModel model);
+    IEnumerable<IRegressionModel> Models { get; }
+    IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionEnsembleSolution.cs	(revision 7570)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Core;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IRegressionEnsembleSolution : IRegressionSolution {
+    new IRegressionEnsembleModel Model { get; }
+    new RegressionEnsembleProblemData ProblemData { get; set; }
+    IItemCollection<IRegressionSolution> RegressionSolutions { get; }
+    IEnumerable<IEnumerable<double>> GetEstimatedValueVectors(Dataset dataset, IEnumerable<int> rows);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionModel.cs	(revision 7570)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IRegressionModel : IDataAnalysisModel {
+    IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows);
+    IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData);
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblem.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblem.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblem.cs	(revision 7570)
@@ -0,0 +1,25 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IRegressionProblem : IDataAnalysisProblem<IRegressionProblemData> {
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionProblemData.cs	(revision 7570)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IRegressionProblemData : IDataAnalysisProblemData {
+    string TargetVariable { get; }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionSolution.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionSolution.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Regression/IRegressionSolution.cs	(revision 7570)
@@ -0,0 +1,44 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+namespace HeuristicLab.Problems.DataAnalysis {
+  public interface IRegressionSolution : IDataAnalysisSolution {
+    new IRegressionModel Model { get; }
+    new IRegressionProblemData ProblemData { get; set; }
+
+    IEnumerable<double> EstimatedValues { get; }
+    IEnumerable<double> EstimatedTrainingValues { get; }
+    IEnumerable<double> EstimatedTestValues { get; }
+    IEnumerable<double> GetEstimatedValues(IEnumerable<int> rows);
+
+    double TrainingMeanSquaredError { get; }
+    double TestMeanSquaredError { get; }
+    double TrainingMeanAbsoluteError { get; }
+    double TestMeanAbsoluteError { get; }
+    double TrainingRSquared { get; }
+    double TestRSquared { get; }
+    double TrainingRelativeError { get; }
+    double TestRelativeError { get; }
+    double TrainingNormalizedMeanSquaredError { get; }
+    double TestNormalizedMeanSquaredError { get; }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/NormalizedGiniCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/NormalizedGiniCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/NormalizedGiniCalculator.cs	(revision 7570)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Problems.DataAnalysis {
+  public class NormalizedGiniCalculator {
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      var originalValuesArr = originalValues.ToArray();
+      var estimatedValuesArr = estimatedValues.ToArray();
+      if (originalValuesArr.Count() != estimatedValuesArr.Count()) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
+      }
+      double oe = Gini(originalValuesArr, estimatedValuesArr, out errorState);
+      if (errorState != OnlineCalculatorError.None) return double.NaN;
+
+      return oe / (Gini(originalValuesArr, originalValuesArr, out errorState));
+    }
+
+    private static double Gini(IEnumerable<double> original, IEnumerable<double> estimated, out OnlineCalculatorError errorState) {
+      var pairs =
+        estimated.Zip(original, (e, o) => new { e, o })
+          .OrderByDescending(p => p.e);
+      if (pairs.Any()) errorState = OnlineCalculatorError.None;
+      else errorState = OnlineCalculatorError.InsufficientElementsAdded;
+      double giniSum = 0.0;
+      double sumOriginal = 0.0;
+      int n = 0;
+      foreach (var p in pairs) {
+        if (double.IsNaN(p.o) || double.IsNaN(p.e)) {
+          errorState = OnlineCalculatorError.InvalidValueAdded;
+          return double.NaN;
+        }
+        sumOriginal += p.o;
+        giniSum += sumOriginal;
+        n++;
+      }
+      giniSum /= sumOriginal;
+
+      return (giniSum - ((n + 1) / 2.0)) / n;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineAccuracyCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineAccuracyCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineAccuracyCalculator.cs	(revision 7570)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 OnlineAccuracyCalculator : IOnlineCalculator {
+
+    private int correctlyClassified;
+    private int n;
+    public double Accuracy {
+      get {
+        return correctlyClassified / (double)n;
+      }
+    }
+
+    public OnlineAccuracyCalculator() {
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError ErrorState {
+      get { return errorState; }
+    }
+    public double Value {
+      get { return Accuracy; }
+    }
+    public void Reset() {
+      n = 0;
+      correctlyClassified = 0;
+      errorState = OnlineCalculatorError.InsufficientElementsAdded;
+    }
+
+    public void Add(double original, double estimated) {
+      // ignore cases where original is NaN completly 
+      if (!double.IsNaN(original)) {
+        // increment number of observed samples
+        n++;
+        if (original.IsAlmost(estimated)) {
+          // original = estimated = +Inf counts as correctly classified
+          // original = estimated = -Inf counts as correctly classified
+          correctlyClassified++;
+        }
+        errorState = OnlineCalculatorError.None; // number of (non-NaN) samples >= 1
+      }
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineAccuracyCalculator accuracyCalculator = new OnlineAccuracyCalculator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        accuracyCalculator.Add(original, estimated);
+        if (accuracyCalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (accuracyCalculator.ErrorState == OnlineCalculatorError.None &&
+          (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
+      } else {
+        errorState = accuracyCalculator.ErrorState;
+        return accuracyCalculator.Accuracy;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineCovarianceCalcualtor.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineCovarianceCalcualtor.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineCovarianceCalcualtor.cs	(revision 7570)
@@ -0,0 +1,97 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineCovarianceCalculator : IOnlineCalculator {
+
+    private double xMean, yMean, Cn;
+    private int n;
+    public double Covariance {
+      get {
+        return n > 0 ? Cn / n : 0.0;
+      }
+    }
+
+    public OnlineCovarianceCalculator() {
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError ErrorState {
+      get { return errorState; }
+    }
+    public double Value {
+      get { return Covariance; }
+    }
+    public void Reset() {
+      n = 0;
+      Cn = 0.0;
+      xMean = 0.0;
+      yMean = 0.0;
+      errorState = OnlineCalculatorError.InsufficientElementsAdded;
+    }
+
+    public void Add(double x, double y) {
+      if (double.IsNaN(y) || double.IsInfinity(y) || double.IsNaN(x) || double.IsInfinity(x) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
+        errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
+      } else {
+        n++;
+        errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
+
+        // online calculation of tMean
+        xMean = xMean + (x - xMean) / n;
+        double delta = y - yMean; // delta = (y - yMean(n-1))
+        yMean = yMean + delta / n;
+
+        // online calculation of covariance
+        Cn = Cn + delta * (x - xMean); // C(n) = C(n-1) + (y - yMean(n-1)) (t - tMean(n))       
+      }
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> first, IEnumerable<double> second, out OnlineCalculatorError errorState) {
+      IEnumerator<double> firstEnumerator = first.GetEnumerator();
+      IEnumerator<double> secondEnumerator = second.GetEnumerator();
+      OnlineCovarianceCalculator covarianceCalculator = new OnlineCovarianceCalculator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (firstEnumerator.MoveNext() & secondEnumerator.MoveNext()) {
+        double x = secondEnumerator.Current;
+        double y = firstEnumerator.Current;
+        covarianceCalculator.Add(x, y);
+        if (covarianceCalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (covarianceCalculator.ErrorState == OnlineCalculatorError.None &&
+          (secondEnumerator.MoveNext() || firstEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in first and second enumeration doesn't match.");
+      } else {
+        errorState = covarianceCalculator.ErrorState;
+        return covarianceCalculator.Covariance;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineLinearScalingParameterCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineLinearScalingParameterCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineLinearScalingParameterCalculator.cs	(revision 7570)
@@ -0,0 +1,123 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 OnlineLinearScalingParameterCalculator {
+
+    /// <summary>
+    /// Additive constant
+    /// </summary>
+    public double Alpha {
+      get {
+        return targetMeanCalculator.Mean - Beta * originalMeanAndVarianceCalculator.Mean;
+      }
+    }
+
+    /// <summary>
+    /// Multiplicative factor
+    /// </summary>
+    public double Beta {
+      get {
+        if (originalMeanAndVarianceCalculator.PopulationVariance.IsAlmost(0.0))
+          return 1;
+        else
+          return originalTargetCovarianceCalculator.Covariance / originalMeanAndVarianceCalculator.PopulationVariance;
+      }
+    }
+
+    public OnlineCalculatorError ErrorState {
+      get {
+        return targetMeanCalculator.MeanErrorState | originalMeanAndVarianceCalculator.MeanErrorState |
+          originalMeanAndVarianceCalculator.PopulationVarianceErrorState | originalTargetCovarianceCalculator.ErrorState;
+      }
+    }
+
+    private int cnt;
+    private OnlineMeanAndVarianceCalculator targetMeanCalculator;
+    private OnlineMeanAndVarianceCalculator originalMeanAndVarianceCalculator;
+    private OnlineCovarianceCalculator originalTargetCovarianceCalculator;
+
+    public OnlineLinearScalingParameterCalculator() {
+      targetMeanCalculator = new OnlineMeanAndVarianceCalculator();
+      originalMeanAndVarianceCalculator = new OnlineMeanAndVarianceCalculator();
+      originalTargetCovarianceCalculator = new OnlineCovarianceCalculator();
+      Reset();
+    }
+
+    public void Reset() {
+      cnt = 0;
+      targetMeanCalculator.Reset();
+      originalMeanAndVarianceCalculator.Reset();
+      originalTargetCovarianceCalculator.Reset();
+    }
+
+    /// <summary>
+    /// Calculates linear scaling parameters in one pass.
+    /// The formulas to calculate the scaling parameters were taken from Scaled Symblic Regression by Maarten Keijzer.
+    /// http://www.springerlink.com/content/x035121165125175/
+    /// </summary>
+    public void Add(double original, double target) {
+      // validity of values is checked in mean calculator and covariance calculator
+      targetMeanCalculator.Add(target);
+      originalMeanAndVarianceCalculator.Add(original);
+      originalTargetCovarianceCalculator.Add(original, target);
+
+      cnt++;
+    }
+
+    /// <summary>
+    /// Calculates alpha and beta parameters to linearly scale elements of original to the scale and location of target
+    /// original[i] * beta + alpha
+    /// </summary>
+    /// <param name="original">Values that should be scaled</param>
+    /// <param name="target">Target values to which the original values should be scaled</param>
+    /// <param name="alpha">Additive constant for the linear scaling</param>
+    /// <param name="beta">Multiplicative factor for the linear scaling</param>
+    /// <param name="errorState">Flag that indicates if errors occurred in the calculation of the linea scaling parameters.</param>
+    public static void Calculate(IEnumerable<double> original, IEnumerable<double> target, out double alpha, out double beta, out OnlineCalculatorError errorState) {
+      OnlineLinearScalingParameterCalculator calculator = new OnlineLinearScalingParameterCalculator();
+      IEnumerator<double> originalEnumerator = original.GetEnumerator();
+      IEnumerator<double> targetEnumerator = target.GetEnumerator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & targetEnumerator.MoveNext()) {
+        double originalElement = originalEnumerator.Current;
+        double targetElement = targetEnumerator.Current;
+        calculator.Add(originalElement, targetElement);
+        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 &&
+            (originalEnumerator.MoveNext() || targetEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in original and target enumeration do not match.");
+      } else {
+        errorState = calculator.ErrorState;
+        alpha = calculator.Alpha;
+        beta = calculator.Beta;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsoluteErrorCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsoluteErrorCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsoluteErrorCalculator.cs	(revision 7570)
@@ -0,0 +1,90 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineMeanAbsoluteErrorCalculator : IOnlineCalculator {
+
+    private double sae;
+    private int n;
+    public double MeanAbsoluteError {
+      get {
+        return n > 0 ? sae / n : 0.0;
+      }
+    }
+
+    public OnlineMeanAbsoluteErrorCalculator() {
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError ErrorState {
+      get { return errorState; }
+    }
+    public double Value {
+      get { return MeanAbsoluteError; }
+    }
+    public void Reset() {
+      n = 0;
+      sae = 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;
+        sae += Math.Abs(error);
+        n++;
+        errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
+      }
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineMeanAbsoluteErrorCalculator maeCalculator = new OnlineMeanAbsoluteErrorCalculator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        maeCalculator.Add(original, estimated);
+        if (maeCalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (maeCalculator.ErrorState == OnlineCalculatorError.None &&
+         (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
+      } else {
+        errorState = maeCalculator.ErrorState;
+        return maeCalculator.MeanAbsoluteError;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsolutePercentageErrorCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsolutePercentageErrorCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsolutePercentageErrorCalculator.cs	(revision 7570)
@@ -0,0 +1,92 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 OnlineMeanAbsolutePercentageErrorCalculator : IOnlineCalculator {
+
+    private double sre;
+    private int n;
+    public double MeanAbsolutePercentageError {
+      get {
+        return n > 0 ? sre / n : 0.0;
+      }
+    }
+
+    public OnlineMeanAbsolutePercentageErrorCalculator() {
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError ErrorState {
+      get { return errorState; }
+    }
+    public double Value {
+      get { return MeanAbsolutePercentageError; }
+    }
+    public void Reset() {
+      n = 0;
+      sre = 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) ||
+        original.IsAlmost(0.0)) {
+        errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
+      } else {
+        sre += Math.Abs((estimated - original) / original);
+        n++;
+        errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
+      }
+    }
+
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineMeanAbsolutePercentageErrorCalculator calculator = new OnlineMeanAbsolutePercentageErrorCalculator();
+
+      // 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 second estimatedValues doesn't match.");
+      } else {
+        errorState = calculator.ErrorState;
+        return calculator.MeanAbsolutePercentageError;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAndVarianceCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAndVarianceCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAndVarianceCalculator.cs	(revision 7570)
@@ -0,0 +1,109 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineMeanAndVarianceCalculator {
+
+    private double m_oldM, m_newM, m_oldS, m_newS;
+    private int n;
+
+    private OnlineCalculatorError varianceErrorState;
+    public OnlineCalculatorError VarianceErrorState {
+      get { return varianceErrorState; }
+    }
+
+    public double Variance {
+      get {
+        return (n > 1) ? m_newS / (n - 1) : 0.0;
+      }
+    }
+
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError PopulationVarianceErrorState {
+      get { return errorState; }
+    }
+    public double PopulationVariance {
+      get {
+        return (n > 0) ? m_newS / n : 0.0;
+      }
+    }
+
+    public OnlineCalculatorError MeanErrorState {
+      get { return errorState; }
+    }
+    public double Mean {
+      get {
+        return (n > 0) ? m_newM : 0.0;
+      }
+    }
+
+    public int Count {
+      get { return n; }
+    }
+
+    public OnlineMeanAndVarianceCalculator() {
+      Reset();
+    }
+
+    public void Reset() {
+      n = 0;
+      errorState = OnlineCalculatorError.InsufficientElementsAdded;
+      varianceErrorState = OnlineCalculatorError.InsufficientElementsAdded;
+    }
+
+    public void Add(double x) {
+      if (double.IsNaN(x) || double.IsInfinity(x) || x > 1E13 || x < -1E13 || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
+        errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
+        varianceErrorState = errorState | OnlineCalculatorError.InvalidValueAdded;
+      } else {
+        n++;
+        // See Knuth TAOCP vol 2, 3rd edition, page 232
+        if (n == 1) {
+          m_oldM = m_newM = x;
+          m_oldS = 0.0;
+          errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
+        } else {
+
+          varianceErrorState = varianceErrorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 2
+          m_newM = m_oldM + (x - m_oldM) / n;
+          m_newS = m_oldS + (x - m_oldM) * (x - m_newM);
+
+          // set up for next iteration
+          m_oldM = m_newM;
+          m_oldS = m_newS;
+        }
+      }
+    }
+
+    public static void Calculate(IEnumerable<double> x, out double mean, out double variance, out OnlineCalculatorError meanErrorState, out OnlineCalculatorError varianceErrorState) {
+      OnlineMeanAndVarianceCalculator meanAndVarianceCalculator = new OnlineMeanAndVarianceCalculator();
+      foreach (double xi in x) {
+        meanAndVarianceCalculator.Add(xi);
+      }
+      mean = meanAndVarianceCalculator.Mean;
+      variance = meanAndVarianceCalculator.Variance;
+      meanErrorState = meanAndVarianceCalculator.MeanErrorState;
+      varianceErrorState = meanAndVarianceCalculator.VarianceErrorState;
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanErrorCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanErrorCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanErrorCalculator.cs	(revision 7570)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineMeanErrorCalculator : IOnlineCalculator {
+
+    private readonly OnlineMeanAndVarianceCalculator meanAndVarianceCalculator;
+    public double MeanError {
+      get { return meanAndVarianceCalculator.Mean; }
+    }
+
+    public OnlineMeanErrorCalculator() {
+      meanAndVarianceCalculator = new OnlineMeanAndVarianceCalculator();
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    public OnlineCalculatorError ErrorState {
+      get { return meanAndVarianceCalculator.MeanErrorState; }
+    }
+    public double Value {
+      get { return MeanError; }
+    }
+    public void Reset() {
+      meanAndVarianceCalculator.Reset();
+    }
+
+    public void Add(double original, double estimated) {
+      meanAndVarianceCalculator.Add(estimated - original);
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineMeanErrorCalculator meCalculator = new OnlineMeanErrorCalculator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        meCalculator.Add(original, estimated);
+        if (meCalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (meCalculator.ErrorState == OnlineCalculatorError.None &&
+         (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
+      } else {
+        errorState = meCalculator.ErrorState;
+        return meCalculator.MeanError;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanSquaredErrorCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanSquaredErrorCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanSquaredErrorCalculator.cs	(revision 7570)
@@ -0,0 +1,90 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineMeanSquaredErrorCalculator : IOnlineCalculator {
+
+    private double sse;
+    private int n;
+    public double MeanSquaredError {
+      get {
+        return n > 0 ? sse / n : 0.0;
+      }
+    }
+
+    public OnlineMeanSquaredErrorCalculator() {
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    private OnlineCalculatorError errorState;
+    public OnlineCalculatorError ErrorState {
+      get { return errorState; }
+    }
+    public double Value {
+      get { return MeanSquaredError; }
+    }
+    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;
+        sse += error * error;
+        n++;
+        errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
+      }
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineMeanSquaredErrorCalculator mseCalculator = new OnlineMeanSquaredErrorCalculator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        mseCalculator.Add(original, estimated);
+        if (mseCalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (mseCalculator.ErrorState == OnlineCalculatorError.None &&
+         (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
+      } else {
+        errorState = mseCalculator.ErrorState;
+        return mseCalculator.MeanSquaredError;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineNormalizedMeanSquaredErrorCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineNormalizedMeanSquaredErrorCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineNormalizedMeanSquaredErrorCalculator.cs	(revision 7570)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class OnlineNormalizedMeanSquaredErrorCalculator : IOnlineCalculator {
+    private OnlineMeanAndVarianceCalculator meanSquaredErrorCalculator;
+    private OnlineMeanAndVarianceCalculator originalVarianceCalculator;
+
+    public double NormalizedMeanSquaredError {
+      get {
+        double var = originalVarianceCalculator.Variance;
+        double m = meanSquaredErrorCalculator.Mean;
+        return var > 0 ? m / var : 0.0;
+      }
+    }
+
+    public OnlineNormalizedMeanSquaredErrorCalculator() {
+      meanSquaredErrorCalculator = new OnlineMeanAndVarianceCalculator();
+      originalVarianceCalculator = new OnlineMeanAndVarianceCalculator();
+      Reset();
+    }
+
+    #region IOnlineCalculator Members
+    public OnlineCalculatorError ErrorState {
+      get { return meanSquaredErrorCalculator.MeanErrorState | originalVarianceCalculator.VarianceErrorState; }
+    }
+    public double Value {
+      get { return NormalizedMeanSquaredError; }
+    }
+
+    public void Reset() {
+      meanSquaredErrorCalculator.Reset();
+      originalVarianceCalculator.Reset();
+    }
+
+    public void Add(double original, double estimated) {
+      // no need to check for validity of values explicitly as it is checked in the meanAndVariance calculator anyway
+      double error = estimated - original;
+      meanSquaredErrorCalculator.Add(error * error);
+      originalVarianceCalculator.Add(original);
+    }
+    #endregion
+
+    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
+      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
+      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
+      OnlineNormalizedMeanSquaredErrorCalculator normalizedMSECalculator = new OnlineNormalizedMeanSquaredErrorCalculator();
+
+      //needed because otherwise the normalizedMSECalculator is in ErrorState.InsufficientValuesAdded
+      if (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        normalizedMSECalculator.Add(original, estimated);
+      }
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        double original = originalEnumerator.Current;
+        double estimated = estimatedEnumerator.Current;
+        normalizedMSECalculator.Add(original, estimated);
+        if (normalizedMSECalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (normalizedMSECalculator.ErrorState == OnlineCalculatorError.None &&
+           (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumeration doesn't match.");
+      } else {
+        errorState = normalizedMSECalculator.ErrorState;
+        return normalizedMSECalculator.NormalizedMeanSquaredError;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRSquaredCalculator.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRSquaredCalculator.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRSquaredCalculator.cs	(revision 7570)
@@ -0,0 +1,92 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 OnlinePearsonsRSquaredCalculator : IOnlineCalculator {
+    private OnlineCovarianceCalculator covCalculator = new OnlineCovarianceCalculator();
+    private OnlineMeanAndVarianceCalculator sxCalculator = new OnlineMeanAndVarianceCalculator();
+    private OnlineMeanAndVarianceCalculator syCalculator = new OnlineMeanAndVarianceCalculator();
+
+    public double RSquared {
+      get {
+        double xVar = sxCalculator.PopulationVariance;
+        double yVar = syCalculator.PopulationVariance;
+        if (xVar.IsAlmost(0.0) || yVar.IsAlmost(0.0)) {
+          return 0.0;
+        } else {
+          double r = covCalculator.Covariance / (Math.Sqrt(xVar) * Math.Sqrt(yVar));
+          return r * r;
+        }
+      }
+    }
+
+    public OnlinePearsonsRSquaredCalculator() { }
+
+    #region IOnlineCalculator Members
+    public OnlineCalculatorError ErrorState {
+      get { return covCalculator.ErrorState | sxCalculator.PopulationVarianceErrorState | syCalculator.PopulationVarianceErrorState; }
+    }
+    public double Value {
+      get { return RSquared; }
+    }
+    public void Reset() {
+      covCalculator.Reset();
+      sxCalculator.Reset();
+      syCalculator.Reset();
+    }
+
+    public void Add(double x, double y) {
+      // no need to check validity of values explicitly here as it is checked in all three evaluators 
+      covCalculator.Add(x, y);
+      sxCalculator.Add(x);
+      syCalculator.Add(y);
+    }
+
+    #endregion
+
+    public static double Calculate(IEnumerable<double> first, IEnumerable<double> second, out OnlineCalculatorError errorState) {
+      IEnumerator<double> firstEnumerator = first.GetEnumerator();
+      IEnumerator<double> secondEnumerator = second.GetEnumerator();
+      OnlinePearsonsRSquaredCalculator rSquaredCalculator = new OnlinePearsonsRSquaredCalculator();
+
+      // always move forward both enumerators (do not use short-circuit evaluation!)
+      while (firstEnumerator.MoveNext() & secondEnumerator.MoveNext()) {
+        double original = firstEnumerator.Current;
+        double estimated = secondEnumerator.Current;
+        rSquaredCalculator.Add(original, estimated);
+        if (rSquaredCalculator.ErrorState != OnlineCalculatorError.None) break;
+      }
+
+      // check if both enumerators are at the end to make sure both enumerations have the same length
+      if (rSquaredCalculator.ErrorState == OnlineCalculatorError.None &&
+           (secondEnumerator.MoveNext() || firstEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in first and second enumeration doesn't match.");
+      } else {
+        errorState = rSquaredCalculator.ErrorState;
+        return rSquaredCalculator.RSquared;
+      }
+    }
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Plugin.cs.frame
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Plugin.cs.frame	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Plugin.cs.frame	(revision 7570)
@@ -0,0 +1,40 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Text;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [Plugin("HeuristicLab.Problems.DataAnalysis","Provides base classes for data analysis tasks.", "3.4.2.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.DataAnalysis-3.4.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization","3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  public class HeuristicLabProblemsDataAnalysisPlugin : PluginBase {
+  }
+}
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Properties/AssemblyInfo.cs.frame	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/Properties/AssemblyInfo.cs.frame	(revision 7570)
@@ -0,0 +1,55 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// 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.Problems.DataAnalysis")]
+[assembly: AssemblyDescription("Provides base classes for data analysis tasks.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2012 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("460C6FC6-FFBB-4286-B781-06D9F56A202D")]
+
+// 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 Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.4.0.0")]
+[assembly: AssemblyFileVersion("3.4.2.$WCREV$")]
Index: /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/TableFileParser.cs
===================================================================
--- /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/TableFileParser.cs	(revision 7570)
+++ /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Problems.DataAnalysis/3.4/TableFileParser.cs	(revision 7570)
@@ -0,0 +1,435 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Globalization;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  public class TableFileParser {
+    private const int BUFFER_SIZE = 1024;
+    private readonly char[] POSSIBLE_SEPARATORS = new char[] { ',', ';', '\t' };
+    private Tokenizer tokenizer;
+    private List<List<object>> rowValues;
+
+    private int rows;
+    public int Rows {
+      get { return rows; }
+      set { rows = value; }
+    }
+
+    private int columns;
+    public int Columns {
+      get { return columns; }
+      set { columns = value; }
+    }
+
+    private List<IList> values;
+    public List<IList> Values {
+      get {
+        return values;
+      }
+    }
+
+    private List<string> variableNames;
+    public IEnumerable<string> VariableNames {
+      get {
+        if (variableNames.Count > 0) return variableNames;
+        else {
+          string[] names = new string[columns];
+          for (int i = 0; i < names.Length; i++) {
+            names[i] = "X" + i.ToString("000");
+          }
+          return names;
+        }
+      }
+    }
+
+    public TableFileParser() {
+      rowValues = new List<List<object>>();
+      variableNames = new List<string>();
+    }
+
+    public void Parse(string fileName) {
+      NumberFormatInfo numberFormat;
+      DateTimeFormatInfo dateTimeFormatInfo;
+      char separator;
+      DetermineFileFormat(fileName, out numberFormat, out dateTimeFormatInfo, out separator);
+      using (StreamReader reader = new StreamReader(fileName)) {
+        tokenizer = new Tokenizer(reader, numberFormat, dateTimeFormatInfo, separator);
+        // parse the file
+        Parse();
+      }
+
+      // translate the list of samples into a DoubleMatrixData item
+      rows = rowValues.Count;
+      columns = rowValues[0].Count;
+      values = new List<IList>();
+
+      //create columns
+      for (int col = 0; col < columns; col++) {
+        var types = rowValues.Select(r => r[col]).Where(v => v != null && v as string != string.Empty).Take(10).Select(v => v.GetType());
+        if (!types.Any()) {
+          values.Add(new List<string>());
+          continue;
+        }
+
+        var columnType = types.GroupBy(v => v).OrderBy(v => v.Count()).Last().Key;
+        if (columnType == typeof(double)) values.Add(new List<double>());
+        else if (columnType == typeof(DateTime)) values.Add(new List<DateTime>());
+        else if (columnType == typeof(string)) values.Add(new List<string>());
+        else throw new InvalidOperationException();
+      }
+
+
+
+      //fill with values
+      foreach (List<object> row in rowValues) {
+        int columnIndex = 0;
+        foreach (object element in row) {
+          if (values[columnIndex] is List<double> && !(element is double))
+            values[columnIndex].Add(double.NaN);
+          else if (values[columnIndex] is List<DateTime> && !(element is DateTime))
+            values[columnIndex].Add(DateTime.MinValue);
+          else if (values[columnIndex] is List<string> && !(element is string))
+            values[columnIndex].Add(string.Empty);
+          else
+            values[columnIndex].Add(element);
+          columnIndex++;
+        }
+      }
+    }
+
+    private void DetermineFileFormat(string fileName, out NumberFormatInfo numberFormat, out DateTimeFormatInfo dateTimeFormatInfo, out char separator) {
+      using (StreamReader reader = new StreamReader(fileName)) {
+        // skip first line
+        reader.ReadLine();
+        // read a block
+        char[] buffer = new char[BUFFER_SIZE];
+        int charsRead = reader.ReadBlock(buffer, 0, BUFFER_SIZE);
+        // count frequency of special characters
+        Dictionary<char, int> charCounts = buffer.Take(charsRead)
+          .GroupBy(c => c)
+          .ToDictionary(g => g.Key, g => g.Count());
+
+        // depending on the characters occuring in the block 
+        // we distinghish a number of different cases based on the the following rules:
+        // many points => it must be English number format, the other frequently occuring char is the separator
+        // no points but many commas => this is the problematic case. Either German format (real numbers) or English format (only integer numbers) with ',' as separator
+        //   => check the line in more detail:
+        //            English: 0, 0, 0, 0
+        //            German:  0,0 0,0 0,0 ...
+        //            => if commas are followed by space => English format
+        // no points no commas => English format (only integer numbers) use the other frequently occuring char as separator
+        // in all cases only treat ' ' as separator if no other separator is possible (spaces can also occur additionally to separators)
+        if (OccurrencesOf(charCounts, '.') > 10) {
+          numberFormat = NumberFormatInfo.InvariantInfo;
+          dateTimeFormatInfo = DateTimeFormatInfo.InvariantInfo;
+          separator = POSSIBLE_SEPARATORS
+            .Where(c => OccurrencesOf(charCounts, c) > 10)
+            .OrderBy(c => -OccurrencesOf(charCounts, c))
+            .DefaultIfEmpty(' ')
+            .First();
+        } else if (OccurrencesOf(charCounts, ',') > 10) {
+          // no points and many commas
+          // count the number of tokens (chains of only digits and commas) that contain multiple comma characters
+          int tokensWithMultipleCommas = 0;
+          for (int i = 0; i < charsRead; i++) {
+            int nCommas = 0;
+            while (i < charsRead && (buffer[i] == ',' || Char.IsDigit(buffer[i]))) {
+              if (buffer[i] == ',') nCommas++;
+              i++;
+            }
+            if (nCommas > 2) tokensWithMultipleCommas++;
+          }
+          if (tokensWithMultipleCommas > 1) {
+            // English format (only integer values) with ',' as separator
+            numberFormat = NumberFormatInfo.InvariantInfo;
+            dateTimeFormatInfo = DateTimeFormatInfo.InvariantInfo;
+            separator = ',';
+          } else {
+            char[] disallowedSeparators = new char[] { ',' };
+            // German format (real values)
+            numberFormat = NumberFormatInfo.GetInstance(new CultureInfo("de-DE"));
+            dateTimeFormatInfo = DateTimeFormatInfo.GetInstance(new CultureInfo("de-DE"));
+            separator = POSSIBLE_SEPARATORS
+              .Except(disallowedSeparators)
+              .Where(c => OccurrencesOf(charCounts, c) > 10)
+              .OrderBy(c => -OccurrencesOf(charCounts, c))
+              .DefaultIfEmpty(' ')
+              .First();
+          }
+        } else {
+          // no points and no commas => English format
+          numberFormat = NumberFormatInfo.InvariantInfo;
+          dateTimeFormatInfo = DateTimeFormatInfo.InvariantInfo;
+          separator = POSSIBLE_SEPARATORS
+            .Where(c => OccurrencesOf(charCounts, c) > 10)
+            .OrderBy(c => -OccurrencesOf(charCounts, c))
+            .DefaultIfEmpty(' ')
+            .First();
+        }
+      }
+    }
+
+    private int OccurrencesOf(Dictionary<char, int> charCounts, char c) {
+      return charCounts.ContainsKey(c) ? charCounts[c] : 0;
+    }
+
+    #region tokenizer
+    internal enum TokenTypeEnum {
+      NewLine, Separator, String, Double, DateTime
+    }
+
+    internal class Token {
+      public TokenTypeEnum type;
+      public string stringValue;
+      public double doubleValue;
+      public DateTime dateTimeValue;
+
+      public Token(TokenTypeEnum type, string value) {
+        this.type = type;
+        stringValue = value;
+        dateTimeValue = DateTime.MinValue;
+        doubleValue = 0.0;
+      }
+
+      public override string ToString() {
+        return stringValue;
+      }
+    }
+
+
+    internal class Tokenizer {
+      private StreamReader reader;
+      private List<Token> tokens;
+      private NumberFormatInfo numberFormatInfo;
+      private DateTimeFormatInfo dateTimeFormatInfo;
+      private char separator;
+      private const string INTERNAL_SEPARATOR = "#";
+
+      private int currentLineNumber = 0;
+      public int CurrentLineNumber {
+        get { return currentLineNumber; }
+        private set { currentLineNumber = value; }
+      }
+      private string currentLine;
+      public string CurrentLine {
+        get { return currentLine; }
+        private set { currentLine = value; }
+      }
+
+      private Token newlineToken;
+      public Token NewlineToken {
+        get { return newlineToken; }
+        private set { newlineToken = value; }
+      }
+      private Token separatorToken;
+      public Token SeparatorToken {
+        get { return separatorToken; }
+        private set { separatorToken = value; }
+      }
+
+      public Tokenizer(StreamReader reader, NumberFormatInfo numberFormatInfo, DateTimeFormatInfo dateTimeFormatInfo, char separator) {
+        this.reader = reader;
+        this.numberFormatInfo = numberFormatInfo;
+        this.dateTimeFormatInfo = dateTimeFormatInfo;
+        this.separator = separator;
+        separatorToken = new Token(TokenTypeEnum.Separator, INTERNAL_SEPARATOR);
+        newlineToken = new Token(TokenTypeEnum.NewLine, Environment.NewLine);
+        tokens = new List<Token>();
+        ReadNextTokens();
+      }
+
+      private void ReadNextTokens() {
+        if (!reader.EndOfStream) {
+          CurrentLine = reader.ReadLine();
+          var newTokens = from str in Split(CurrentLine)
+                          let trimmedStr = str.Trim()
+                          where !string.IsNullOrEmpty(trimmedStr)
+                          select MakeToken(trimmedStr);
+
+          tokens.AddRange(newTokens);
+          tokens.Add(NewlineToken);
+          CurrentLineNumber++;
+        }
+      }
+
+      private IEnumerable<string> Split(string line) {
+        StringBuilder subStr = new StringBuilder();
+        foreach (char c in line) {
+          if (c == separator) {
+            yield return subStr.ToString();
+            subStr = new StringBuilder();
+            // all separator characters are transformed to the internally used separator character
+            yield return INTERNAL_SEPARATOR;
+          } else {
+            subStr.Append(c);
+          }
+        }
+        yield return subStr.ToString();
+      }
+
+      private Token MakeToken(string strToken) {
+        Token token = new Token(TokenTypeEnum.String, strToken);
+        if (strToken.Equals(INTERNAL_SEPARATOR)) {
+          return SeparatorToken;
+        } else if (double.TryParse(strToken, NumberStyles.Float, numberFormatInfo, out token.doubleValue)) {
+          token.type = TokenTypeEnum.Double;
+          return token;
+        } else if (DateTime.TryParse(strToken, dateTimeFormatInfo, DateTimeStyles.None, out token.dateTimeValue)) {
+          token.type = TokenTypeEnum.DateTime;
+          return token;
+        }
+
+        // couldn't parse the token as an int or float number  or datetime value so return a string token
+        return token;
+      }
+
+      public Token Peek() {
+        return tokens[0];
+      }
+
+      public Token Next() {
+        Token next = tokens[0];
+        tokens.RemoveAt(0);
+        if (tokens.Count == 0) {
+          ReadNextTokens();
+        }
+        return next;
+      }
+
+      public bool HasNext() {
+        return tokens.Count > 0 || !reader.EndOfStream;
+      }
+    }
+    #endregion
+
+    #region parsing
+    private void Parse() {
+      ParseVariableNames();
+      if (!tokenizer.HasNext()) Error("Couldn't parse data values. Probably because of incorrect number format (the parser expects english number format with a '.' as decimal separator).", "", tokenizer.CurrentLineNumber);
+      ParseValues();
+      if (rowValues.Count == 0) Error("Couldn't parse data values. Probably because of incorrect number format (the parser expects english number format with a '.' as decimal separator).", "", tokenizer.CurrentLineNumber);
+    }
+
+    private void ParseValues() {
+      while (tokenizer.HasNext()) {
+        if (tokenizer.Peek() == tokenizer.NewlineToken) {
+          tokenizer.Next();
+        } else {
+          List<object> row = new List<object>();
+          object value = NextValue(tokenizer);
+          row.Add(value);
+          while (tokenizer.HasNext() && tokenizer.Peek() == tokenizer.SeparatorToken) {
+            Expect(tokenizer.SeparatorToken);
+            row.Add(NextValue(tokenizer));
+          }
+          Expect(tokenizer.NewlineToken);
+          // all rows have to have the same number of values            
+          // the first row defines how many samples are needed
+          if (rowValues.Count > 0 && rowValues[0].Count != row.Count) {
+            Error("The first row of the dataset has " + rowValues[0].Count + " columns." +
+                  "\nLine " + tokenizer.CurrentLineNumber + " has " + row.Count + " columns.", "",
+                  tokenizer.CurrentLineNumber);
+          }
+          rowValues.Add(row);
+        }
+      }
+    }
+
+    private object NextValue(Tokenizer tokenizer) {
+      if (tokenizer.Peek() == tokenizer.SeparatorToken || tokenizer.Peek() == tokenizer.NewlineToken) return string.Empty;
+      Token current = tokenizer.Next();
+      if (current.type == TokenTypeEnum.Separator) {
+        return double.NaN;
+      } else if (current.type == TokenTypeEnum.String) {
+        return current.stringValue;
+      } else if (current.type == TokenTypeEnum.Double) {
+        return current.doubleValue;
+      } else if (current.type == TokenTypeEnum.DateTime) {
+        return current.dateTimeValue;
+      }
+      // found an unexpected token => throw error 
+      Error("Unexpected token.", current.stringValue, tokenizer.CurrentLineNumber);
+      // this line is never executed because Error() throws an exception
+      throw new InvalidOperationException();
+    }
+
+    private void ParseVariableNames() {
+      //if first token is double no variables names are given
+      if (tokenizer.Peek().type == TokenTypeEnum.Double) return;
+
+      // the first line must contain variable names
+      List<Token> tokens = new List<Token>();
+      Token valueToken;
+      valueToken = tokenizer.Next();
+      tokens.Add(valueToken);
+      while (tokenizer.HasNext() && tokenizer.Peek() == tokenizer.SeparatorToken) {
+        Expect(tokenizer.SeparatorToken);
+        valueToken = tokenizer.Next();
+        if (valueToken != tokenizer.NewlineToken) {
+          tokens.Add(valueToken);
+        }
+      }
+      if (valueToken != tokenizer.NewlineToken) {
+        Expect(tokenizer.NewlineToken);
+      }
+      variableNames = tokens.Select(x => x.stringValue.Trim()).ToList();
+    }
+
+    private void Expect(Token expectedToken) {
+      Token actualToken = tokenizer.Next();
+      if (actualToken != expectedToken) {
+        Error("Expected: " + expectedToken, actualToken.stringValue, tokenizer.CurrentLineNumber);
+      }
+    }
+
+    private void Error(string message, string token, int lineNumber) {
+      throw new DataFormatException("Error while parsing.\n" + message, token, lineNumber);
+    }
+    #endregion
+
+    [Serializable]
+    private class DataFormatException : Exception {
+      private int line;
+      public int Line {
+        get { return line; }
+      }
+      private string token;
+      public string Token {
+        get { return token; }
+      }
+      public DataFormatException(string message, string token, int line)
+        : base(message + "\nToken: " + token + " (line: " + line + ")") {
+        this.token = token;
+        this.line = line;
+      }
+
+      public DataFormatException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+    }
+  }
+}
