Index: trunk/sources/HeuristicLab 3.3.sln
===================================================================
--- trunk/sources/HeuristicLab 3.3.sln	(revision 4564)
+++ trunk/sources/HeuristicLab 3.3.sln	(revision 4565)
@@ -305,4 +305,8 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab-3.3.Tests", "HeuristicLab\3.3\Tests\HeuristicLab-3.3.Tests.csproj", "{66DABFD5-5BD2-4478-8DF9-C589F569F7A2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.DataAnalysis.Classification-3.3", "HeuristicLab.Problems.DataAnalysis.Classification\3.3\HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj", "{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3", "HeuristicLab.Problems.DataAnalysis.Classification.Views\3.3\HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj", "{7F038E9A-B91E-4F49-8C27-D47BC86F1220}"
 EndProject
 Global
@@ -1375,4 +1379,28 @@
 		{66DABFD5-5BD2-4478-8DF9-C589F569F7A2}.Release|x86.ActiveCfg = Release|x86
 		{66DABFD5-5BD2-4478-8DF9-C589F569F7A2}.Release|x86.Build.0 = Release|x86
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Debug|x64.ActiveCfg = Debug|x64
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Debug|x64.Build.0 = Debug|x64
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Debug|x86.ActiveCfg = Debug|x86
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Debug|x86.Build.0 = Debug|x86
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Release|x64.ActiveCfg = Release|x64
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Release|x64.Build.0 = Release|x64
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Release|x86.ActiveCfg = Release|x86
+		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}.Release|x86.Build.0 = Release|x86
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Debug|x64.ActiveCfg = Debug|x64
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Debug|x64.Build.0 = Debug|x64
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Debug|x86.ActiveCfg = Debug|x86
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Debug|x86.Build.0 = Debug|x86
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Release|x64.ActiveCfg = Release|x64
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Release|x64.Build.0 = Release|x64
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Release|x86.ActiveCfg = Release|x86
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.Designer.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.Designer.cs	(revision 4565)
@@ -0,0 +1,86 @@
+﻿namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  partial class ConfusionMatrixView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.dataGridView = new System.Windows.Forms.DataGridView();
+      this.cmbSamples = new System.Windows.Forms.ComboBox();
+      this.label1 = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // dataGridView
+      // 
+      this.dataGridView.AllowUserToAddRows = false;
+      this.dataGridView.AllowUserToDeleteRows = false;
+      this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.dataGridView.Location = new System.Drawing.Point(3, 30);
+      this.dataGridView.Name = "dataGridView";
+      this.dataGridView.ReadOnly = true;
+      this.dataGridView.Size = new System.Drawing.Size(303, 197);
+      this.dataGridView.TabIndex = 0;
+      // 
+      // cmbSamples
+      // 
+      this.cmbSamples.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.cmbSamples.FormattingEnabled = true;
+      this.cmbSamples.Location = new System.Drawing.Point(56, 3);
+      this.cmbSamples.Name = "cmbSamples";
+      this.cmbSamples.Size = new System.Drawing.Size(121, 21);
+      this.cmbSamples.TabIndex = 1;
+      this.cmbSamples.SelectedIndexChanged += new System.EventHandler(this.cmbSamples_SelectedIndexChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 6);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(47, 13);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "Samples";
+      // 
+      // ConfusionMatrixView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.cmbSamples);
+      this.Controls.Add(this.dataGridView);
+      this.Name = "ConfusionMatrixView";
+      this.Size = new System.Drawing.Size(309, 230);
+      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.DataGridView dataGridView;
+    private System.Windows.Forms.ComboBox cmbSamples;
+    private System.Windows.Forms.Label label1;
+
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.cs	(revision 4565)
@@ -0,0 +1,147 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  [View("Confusion Matrix View")]
+  [Content(typeof(SymbolicClassificationSolution))]
+  public partial class ConfusionMatrixView : AsynchronousContentView {
+    private const string TrainingSamples = "Training";
+    private const string TestSamples = "Test";
+    public ConfusionMatrixView() {
+      InitializeComponent();
+      cmbSamples.Items.Add(TrainingSamples);
+      cmbSamples.Items.Add(TestSamples);
+      cmbSamples.SelectedIndex = 0;
+    }
+
+    public new SymbolicClassificationSolution Content {
+      get { return (SymbolicClassificationSolution)base.Content; }
+      set { base.Content = value; }
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.EstimatedValuesChanged += new EventHandler(Content_EstimatedValuesChanged);
+      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
+      Content.ThresholdsChanged += new EventHandler(Content_ThresholdsChanged);
+    }
+
+
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+      Content.EstimatedValuesChanged -= new EventHandler(Content_EstimatedValuesChanged);
+      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
+      Content.ThresholdsChanged -= new EventHandler(Content_ThresholdsChanged);
+    }
+
+    private void Content_EstimatedValuesChanged(object sender, EventArgs e) {
+      FillDataGridView();
+    }
+    private void Content_ProblemDataChanged(object sender, EventArgs e) {
+      UpdateDataGridView();
+    }
+    private void Content_ThresholdsChanged(object sender, EventArgs e) {
+      FillDataGridView();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      UpdateDataGridView();
+    }
+
+    private void UpdateDataGridView() {
+      if (InvokeRequired) Invoke((Action)UpdateDataGridView);
+      else {
+        if (Content == null) {
+          dataGridView.RowCount = 1;
+          dataGridView.ColumnCount = 1;
+        } else {
+          dataGridView.ColumnCount = Content.ProblemData.NumberOfClasses;
+          dataGridView.RowCount = Content.ProblemData.NumberOfClasses;
+
+          int i = 0;
+          foreach (string headerText in Content.ProblemData.ClassNames) {
+            dataGridView.Columns[i].HeaderText = "Actual " + headerText;
+            dataGridView.Rows[i].HeaderCell.Value = "Predicted " + headerText;
+            i++;
+          }
+          dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.ColumnHeader);
+          dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders);
+
+          FillDataGridView();
+        }
+      }
+    }
+
+    private void FillDataGridView() {
+      if (InvokeRequired) Invoke((Action)FillDataGridView);
+      else {
+        if (Content == null) return;
+
+        double[,] confusionMatrix = new double[Content.ProblemData.NumberOfClasses, Content.ProblemData.NumberOfClasses];
+        IEnumerable<int> rows;
+
+        if (cmbSamples.SelectedItem.ToString() == TrainingSamples) {
+          rows = Content.ProblemData.TrainingIndizes;
+        } else if (cmbSamples.SelectedItem.ToString() == TestSamples) {
+          rows = Content.ProblemData.TestIndizes;
+        } else throw new InvalidOperationException();
+
+        Dictionary<double, int> classValueIndexMapping = new Dictionary<double, int>();
+        int index = 0;
+        foreach (double classValue in Content.ProblemData.SortedClassValues) {
+          classValueIndexMapping.Add(classValue, index);
+          index++;
+        }
+
+        double[] targetValues = Content.ProblemData.Dataset.GetEnumeratedVariableValues(Content.ProblemData.TargetVariable.Value, rows).ToArray();
+        double[] predictedValues = Content.GetEstimatedClassValues(rows).ToArray();
+
+        for (int i = 0; i < targetValues.Length; i++) {
+          double targetValue = targetValues[i];
+          double predictedValue = predictedValues[i];
+          int targetIndex = classValueIndexMapping[targetValue];
+          int predictedIndex = classValueIndexMapping[predictedValue];
+
+          confusionMatrix[predictedIndex, targetIndex] += 1;
+        }
+
+        for (int row = 0; row < confusionMatrix.GetLength(0); row++) {
+          for (int col = 0; col < confusionMatrix.GetLength(1); col++) {
+            //TODO add scaling to relative values;
+            dataGridView[col, row].Value = confusionMatrix[row, col];
+          }
+        }
+      }
+    }
+
+    private void cmbSamples_SelectedIndexChanged(object sender, System.EventArgs e) {
+      FillDataGridView();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj	(revision 4565)
@@ -0,0 +1,194 @@
+﻿<?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>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{7F038E9A-B91E-4F49-8C27-D47BC86F1220}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.DataAnalysis.Classification.Views</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Forms.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConfusionMatrixView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ConfusionMatrixView.Designer.cs">
+      <DependentUpon>ConfusionMatrixView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RocCurvesView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="RocCurvesView.Designer.cs">
+      <DependentUpon>RocCurvesView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="SymbolicClassificationSolutionView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="SymbolicClassificationSolutionView.Designer.cs">
+      <DependentUpon>SymbolicClassificationSolutionView.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+    </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>
+    </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>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.MainForm.WindowsForms\3.3\HeuristicLab.MainForm.WindowsForms-3.3.csproj">
+      <Project>{AB687BBE-1BFE-476B-906D-44237135431D}</Project>
+      <Name>HeuristicLab.MainForm.WindowsForms-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.MainForm\3.3\HeuristicLab.MainForm-3.3.csproj">
+      <Project>{3BD61258-31DA-4B09-89C0-4F71FEF5F05A}</Project>
+      <Name>HeuristicLab.MainForm-3.3</Name>
+    </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>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis.Classification\3.3\HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj">
+      <Project>{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}</Project>
+      <Name>HeuristicLab.Problems.DataAnalysis.Classification-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis.Regression\3.3\HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj">
+      <Project>{BDF86B1D-630E-4CE2-8A49-8C90B1BDE4C9}</Project>
+      <Name>HeuristicLab.Problems.DataAnalysis.Regression-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis\3.3\HeuristicLab.Problems.DataAnalysis-3.3.csproj">
+      <Project>{70DFD984-B1D9-46FE-8EB7-4DE92D71A9FC}</Project>
+      <Name>HeuristicLab.Problems.DataAnalysis-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+SubWCRev "%25ProjectDir%25\" "%25ProjectDir%25HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame" "%25ProjectDir%25\HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs"</PreBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame	(revision 4565)
@@ -0,0 +1,37 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  [Plugin("HeuristicLab.Problems.DataAnalysis.Classification.Views", "3.3.1.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm", "3.3")]
+  [PluginDependency("HeuristicLab.MainForm.WindowsForms", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis.Classification", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis.Regression", "3.3")]
+  public class HeuristicLabProblemsDataAnalysisClassificationViewsPlugin : PluginBase {
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/Properties/AssemblyInfo.frame
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/Properties/AssemblyInfo.frame	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/Properties/AssemblyInfo.frame	(revision 4565)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Classification.Views")]
+[assembly: AssemblyDescription("HeuristicLab DataAnalysis Classification Views")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2010 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("81f6afd4-4c1f-4867-8c11-726e242dd7cb")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.1.0")]
+[assembly: AssemblyFileVersion("3.3.1.$WCREV$")]
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.Designer.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.Designer.cs	(revision 4565)
@@ -0,0 +1,98 @@
+﻿namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  partial class RocCurvesView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+      this.chart = new System.Windows.Forms.DataVisualization.Charting.Chart();
+      this.label1 = new System.Windows.Forms.Label();
+      this.cmbSamples = new System.Windows.Forms.ComboBox();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      chartArea1.Name = "ChartArea1";
+      this.chart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Legend1";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(0, 28);
+      this.chart.Name = "chart";
+      this.chart.Size = new System.Drawing.Size(366, 202);
+      this.chart.TabIndex = 0;
+      this.chart.Text = "chart";
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 6);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(47, 13);
+      this.label1.TabIndex = 4;
+      this.label1.Text = "Samples";
+      // 
+      // cmbSamples
+      // 
+      this.cmbSamples.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.cmbSamples.FormattingEnabled = true;
+      this.cmbSamples.Location = new System.Drawing.Point(56, 3);
+      this.cmbSamples.Name = "cmbSamples";
+      this.cmbSamples.Size = new System.Drawing.Size(121, 21);
+      this.cmbSamples.TabIndex = 3;
+      this.cmbSamples.SelectedIndexChanged += new System.EventHandler(this.cmbSamples_SelectedIndexChanged);
+      // 
+      // RocCurvesView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.cmbSamples);
+      this.Controls.Add(this.chart);
+      this.Name = "RocCurvesView";
+      this.Size = new System.Drawing.Size(366, 230);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.DataVisualization.Charting.Chart chart;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.ComboBox cmbSamples;
+    private System.Windows.Forms.ToolTip toolTip;
+
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.cs	(revision 4565)
@@ -0,0 +1,258 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Common;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  [View("ROC Curves View")]
+  [Content(typeof(SymbolicClassificationSolution))]
+  public partial class RocCurvesView : AsynchronousContentView {
+    private const string xAxisTitle = "False Positive Rate";
+    private const string yAxisTitle = "True Positive Rate";
+    private const string TrainingSamples = "Training";
+    private const string TestSamples = "Test";
+    private Dictionary<string, List<ROCPoint>> cachedRocPoints;
+
+    public RocCurvesView() {
+      InitializeComponent();
+
+      cachedRocPoints = new Dictionary<string, List<ROCPoint>>();
+
+      cmbSamples.Items.Add(TrainingSamples);
+      cmbSamples.Items.Add(TestSamples);
+      cmbSamples.SelectedIndex = 0;
+
+      chart.ChartAreas[0].AxisX.Minimum = 0.0;
+      chart.ChartAreas[0].AxisX.Maximum = 1.0;
+      chart.ChartAreas[0].AxisX.MajorGrid.Interval = 0.2;
+      chart.ChartAreas[0].AxisY.Minimum = 0.0;
+      chart.ChartAreas[0].AxisY.Maximum = 1.0;
+      chart.ChartAreas[0].AxisY.MajorGrid.Interval = 0.2;
+
+      chart.ChartAreas[0].AxisX.Title = xAxisTitle;
+      chart.ChartAreas[0].AxisY.Title = yAxisTitle;
+    }
+
+    public new SymbolicClassificationSolution Content {
+      get { return (SymbolicClassificationSolution)base.Content; }
+      set { base.Content = value; }
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.EstimatedValuesChanged += new EventHandler(Content_EstimatedValuesChanged);
+      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
+    }
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+      Content.EstimatedValuesChanged -= new EventHandler(Content_EstimatedValuesChanged);
+      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
+    }
+
+    private void Content_EstimatedValuesChanged(object sender, EventArgs e) {
+      UpdateChart();
+    }
+    private void Content_ProblemDataChanged(object sender, EventArgs e) {
+      UpdateChart();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      chart.Series.Clear();
+      if (Content != null) UpdateChart();
+    }
+
+    private void UpdateChart() {
+      if (InvokeRequired) Invoke((Action)UpdateChart);
+      else {
+        chart.Series.Clear();
+        chart.Annotations.Clear();
+        cachedRocPoints.Clear();
+
+        int slices = 100;
+        IEnumerable<int> rows;
+
+        if (cmbSamples.SelectedItem.ToString() == TrainingSamples) {
+          rows = Content.ProblemData.TrainingIndizes;
+        } else if (cmbSamples.SelectedItem.ToString() == TestSamples) {
+          rows = Content.ProblemData.TestIndizes;
+        } else throw new InvalidOperationException();
+
+        double[] estimatedValues = Content.GetEstimatedValues(rows).ToArray();
+        double[] targetClassValues = Content.ProblemData.Dataset.GetEnumeratedVariableValues(Content.ProblemData.TargetVariable.Value, rows).ToArray();
+        double minThreshold = estimatedValues.Min();
+        double maxThreshold = estimatedValues.Max();
+        double thresholdIncrement = (maxThreshold - minThreshold) / slices;
+        minThreshold -= thresholdIncrement;
+        maxThreshold += thresholdIncrement;
+
+        List<double> classValues = Content.ProblemData.SortedClassValues.ToList();
+
+        foreach (double classValue in classValues) {
+          List<ROCPoint> rocPoints = new List<ROCPoint>();
+          int positives = targetClassValues.Where(c => c.IsAlmost(classValue)).Count();
+          int negatives = targetClassValues.Length - positives;
+
+          for (double lowerThreshold = minThreshold; lowerThreshold < maxThreshold; lowerThreshold += thresholdIncrement) {
+            for (double upperThreshold = lowerThreshold + thresholdIncrement; upperThreshold < maxThreshold; upperThreshold += thresholdIncrement) {
+              int truePositives = 0;
+              int falsePositives = 0;
+
+              for (int row = 0; row < estimatedValues.Length; row++) {
+                if (lowerThreshold < estimatedValues[row] && estimatedValues[row] < upperThreshold) {
+                  if (targetClassValues[row].IsAlmost(classValue)) truePositives++;
+                  else falsePositives++;
+                }
+              }
+
+              double truePositiveRate = ((double)truePositives) / positives;
+              double falsePositiveRate = ((double)falsePositives) / negatives;
+
+              ROCPoint rocPoint = new ROCPoint(truePositiveRate, falsePositiveRate, lowerThreshold, upperThreshold);
+              if (!rocPoints.Any(x => x.truePositiveRate >= rocPoint.truePositiveRate && x.falsePositiveRate <= rocPoint.falsePositiveRate)) {
+                rocPoints.RemoveAll(x => x.falsePositiveRate >= rocPoint.falsePositiveRate && x.truePositiveRate <= rocPoint.truePositiveRate);
+                rocPoints.Add(rocPoint);
+              }
+            }
+          }
+
+          string className = Content.ProblemData.ClassNames.ElementAt(classValues.IndexOf(classValue));
+          cachedRocPoints[className] = rocPoints.OrderBy(x => x.falsePositiveRate).ToList(); ;
+
+          Series series = new Series(className);
+          series.ChartType = SeriesChartType.Line;
+          series.MarkerStyle = MarkerStyle.Diamond;
+          series.MarkerSize = 5;
+          chart.Series.Add(series);
+          FillSeriesWithDataPoints(series, cachedRocPoints[className]);
+
+          double auc = CalculateAreaUnderCurve(series);
+          series.LegendToolTip = "AUC: " + auc;
+        }
+      }
+    }
+
+    private void FillSeriesWithDataPoints(Series series, IEnumerable<ROCPoint> rocPoints) {
+      series.Points.Add(new DataPoint(0, 0));
+      foreach (ROCPoint rocPoint in rocPoints) {
+        DataPoint point = new DataPoint();
+        point.XValue = rocPoint.falsePositiveRate;
+        point.YValues[0] = rocPoint.truePositiveRate;
+        point.Tag = rocPoint;
+
+        StringBuilder sb = new StringBuilder();
+        sb.AppendLine("True Positive Rate: " + rocPoint.truePositiveRate);
+        sb.AppendLine("False Positive Rate: " + rocPoint.falsePositiveRate);
+        sb.AppendLine("Upper Threshold: " + rocPoint.upperThreshold);
+        sb.AppendLine("Lower Threshold: " + rocPoint.lowerThreshold);
+        point.ToolTip = sb.ToString();
+
+        series.Points.Add(point);
+      }
+      series.Points.Add(new DataPoint(1, 1));
+    }
+
+    private double CalculateAreaUnderCurve(Series series) {
+      if (series.Points.Count < 1) throw new ArgumentException("Could not calculate area under curve if less than 1 data points were given.");
+
+      double auc = 0.0;
+      for (int i = 1; i < series.Points.Count; i++) {
+        double width = series.Points[i].XValue - series.Points[i - 1].XValue;
+        double y1 = series.Points[i - 1].YValues[0];
+        double y2 = series.Points[i].YValues[0];
+
+        auc += (y1 + y2) * width / 2;
+      }
+
+      return auc;
+    }
+
+    private void cmbSamples_SelectedIndexChanged(object sender, System.EventArgs e) {
+      if (Content != null)
+        UpdateChart();
+    }
+
+
+    #region show / hide series
+    private void ToggleSeries(Series series) {
+      if (series.Points.Count == 0)
+        FillSeriesWithDataPoints(series, cachedRocPoints[series.Name]);
+      else
+        series.Points.Clear();
+    }
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        if (result.Series != null) ToggleSeries(result.Series);
+      }
+    }
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = series.Points.Count == 0;
+          foreach (LegendCell cell in legendItem.Cells)
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+        }
+      }
+    }
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+
+      string newTooltipText = string.Empty;
+      if (result.ChartElementType == ChartElementType.DataPoint)
+        newTooltipText = ((DataPoint)result.Object).ToolTip;
+
+      string oldTooltipText = this.toolTip.GetToolTip(chart);
+      if (newTooltipText != oldTooltipText)
+        this.toolTip.SetToolTip(chart, newTooltipText);
+    }
+    #endregion
+
+
+    private class ROCPoint {
+      public ROCPoint(double truePositiveRate, double falsePositiveRate, double lowerThreshold, double upperThreshold) {
+        this.truePositiveRate = truePositiveRate;
+        this.falsePositiveRate = falsePositiveRate;
+        this.lowerThreshold = lowerThreshold;
+        this.upperThreshold = upperThreshold;
+
+      }
+      public double truePositiveRate { get; private set; }
+      public double falsePositiveRate { get; private set; }
+      public double lowerThreshold { get; private set; }
+      public double upperThreshold { get; private set; }
+    }
+
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.Designer.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.Designer.cs	(revision 4565)
@@ -0,0 +1,101 @@
+﻿namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  partial class SymbolicClassificationSolutionView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+      this.chart = new System.Windows.Forms.DataVisualization.Charting.Chart();
+      this.JitterTrackBar = new System.Windows.Forms.TrackBar();
+      this.label1 = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.JitterTrackBar)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      chartArea1.Name = "ChartArea1";
+      this.chart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Legend1";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(3, 3);
+      this.chart.Name = "chart";
+      this.chart.Size = new System.Drawing.Size(553, 364);
+      this.chart.TabIndex = 0;
+      this.chart.Text = "chart";
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.AnnotationPositionChanging += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.AnnotationPositionChangingEventArgs>(this.chart_AnnotationPositionChanging);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // JitterTrackBar
+      // 
+      this.JitterTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.JitterTrackBar.BackColor = System.Drawing.SystemColors.Window;
+      this.JitterTrackBar.Location = new System.Drawing.Point(483, 341);
+      this.JitterTrackBar.Maximum = 100;
+      this.JitterTrackBar.Name = "JitterTrackBar";
+      this.JitterTrackBar.Size = new System.Drawing.Size(71, 45);
+      this.JitterTrackBar.TabIndex = 1;
+      this.JitterTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
+      this.JitterTrackBar.ValueChanged += new System.EventHandler(this.JitterTrackBar_ValueChanged);
+      // 
+      // label1
+      // 
+      this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.label1.AutoSize = true;
+      this.label1.BackColor = System.Drawing.SystemColors.Window;
+      this.label1.Location = new System.Drawing.Point(448, 345);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(32, 13);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "Jitter:";
+      // 
+      // SymbolicClassificationSolutionView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.JitterTrackBar);
+      this.Controls.Add(this.chart);
+      this.Name = "SymbolicClassificationSolutionView";
+      this.Size = new System.Drawing.Size(559, 370);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.JitterTrackBar)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.DataVisualization.Charting.Chart chart;
+    private System.Windows.Forms.TrackBar JitterTrackBar;
+    private System.Windows.Forms.Label label1;
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.cs	(revision 4565)
@@ -0,0 +1,275 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Common;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification.Views {
+  [View("Symbolic Classification View")]
+  [Content(typeof(SymbolicClassificationSolution), true)]
+  public sealed partial class SymbolicClassificationSolutionView : AsynchronousContentView {
+    private const double TrainingAxisValue = 0.0;
+    private const double TestAxisValue = 10.0;
+    private const double TrainingTestBorder = (TestAxisValue - TrainingAxisValue) / 2;
+    private const string TrainingLabelText = "Training Samples";
+    private const string TestLabelText = "Test Samples";
+
+    public new SymbolicClassificationSolution Content {
+      get { return (SymbolicClassificationSolution)base.Content; }
+      set { base.Content = value; }
+    }
+
+    private Dictionary<double, Series> classValueSeriesMapping;
+    private Random random;
+    private bool updateInProgress;
+
+    public SymbolicClassificationSolutionView()
+      : base() {
+      InitializeComponent();
+
+      classValueSeriesMapping = new Dictionary<double, Series>();
+      random = new Random();
+      updateInProgress = false;
+
+      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
+      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
+      this.chart.ChartAreas[0].AxisX.Minimum = TrainingAxisValue - TrainingTestBorder;
+      this.chart.ChartAreas[0].AxisX.Maximum = TestAxisValue + TrainingTestBorder;
+      AddCustomLabelToAxis(this.chart.ChartAreas[0].AxisX);
+
+      this.chart.ChartAreas[0].AxisY.Title = "Estimated Values";
+      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
+      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
+    }
+
+    private void AddCustomLabelToAxis(Axis axis) {
+      CustomLabel trainingLabel = new CustomLabel();
+      trainingLabel.Text = TrainingLabelText;
+      trainingLabel.FromPosition = TrainingAxisValue - TrainingTestBorder;
+      trainingLabel.ToPosition = TrainingAxisValue + TrainingTestBorder;
+      axis.CustomLabels.Add(trainingLabel);
+
+      CustomLabel testLabel = new CustomLabel();
+      testLabel.Text = TestLabelText;
+      testLabel.FromPosition = TestAxisValue - TrainingTestBorder;
+      testLabel.ToPosition = TestAxisValue + TrainingTestBorder;
+      axis.CustomLabels.Add(testLabel);
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.EstimatedValuesChanged += new EventHandler(Content_EstimatedValuesChanged);
+      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
+      Content.ThresholdsChanged += new EventHandler(Content_ThresholdsChanged);
+    }
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+      Content.EstimatedValuesChanged -= new EventHandler(Content_EstimatedValuesChanged);
+      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
+      Content.ThresholdsChanged -= new EventHandler(Content_ThresholdsChanged);
+    }
+
+    private void Content_ProblemDataChanged(object sender, EventArgs e) {
+      UpdateChart();
+    }
+    private void Content_EstimatedValuesChanged(object sender, EventArgs e) {
+      UpdateChart();
+    }
+    private void Content_ThresholdsChanged(object sender, EventArgs e) {
+      AddThresholds();
+    }
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      UpdateChart();
+    }
+
+    private void UpdateChart() {
+      if (InvokeRequired) Invoke((Action)UpdateChart);
+      else if (!updateInProgress) {
+        updateInProgress = true;
+        chart.Series.Clear();
+        classValueSeriesMapping.Clear();
+        if (Content != null) {
+          IEnumerator<string> classNameEnumerator = Content.ProblemData.ClassNames.GetEnumerator();
+          IEnumerator<double> classValueEnumerator = Content.ProblemData.SortedClassValues.GetEnumerator();
+          while (classNameEnumerator.MoveNext() && classValueEnumerator.MoveNext()) {
+            Series series = new Series(classNameEnumerator.Current);
+            series.ChartType = SeriesChartType.FastPoint;
+            series.Tag = classValueEnumerator.Current;
+            chart.Series.Add(series);
+            classValueSeriesMapping.Add(classValueEnumerator.Current, series);
+            FillSeriesWithDataPoints(series);
+          }
+          AddThresholds();
+        }
+        chart.ChartAreas[0].RecalculateAxesScale();
+        updateInProgress = false;
+      }
+    }
+
+    private void FillSeriesWithDataPoints(Series series) {
+      List<double> estimatedValues = Content.EstimatedValues.ToList();
+      foreach (int row in Content.ProblemData.TrainingIndizes) {
+        double estimatedValue = estimatedValues[row];
+        double targetValue = Content.ProblemData.Dataset[Content.ProblemData.TargetVariable.Value, row];
+        if (targetValue.IsAlmost((double)series.Tag)) {
+          double jitterValue = random.NextDouble() * 2.0 - 1.0;
+          DataPoint point = new DataPoint();
+          point.XValue = TrainingAxisValue + 0.01 * jitterValue * JitterTrackBar.Value * (TrainingTestBorder * 0.9);
+          point.YValues[0] = estimatedValue;
+          point.Tag = new KeyValuePair<double, double>(TrainingAxisValue, jitterValue);
+          series.Points.Add(point);
+        }
+      }
+
+      foreach (int row in Content.ProblemData.TestIndizes) {
+        double estimatedValue = estimatedValues[row];
+        double targetValue = Content.ProblemData.Dataset[Content.ProblemData.TargetVariable.Value, row];
+        if (targetValue == (double)series.Tag) {
+          double jitterValue = random.NextDouble() * 2.0 - 1.0;
+          DataPoint point = new DataPoint();
+          point.XValue = TestAxisValue + 0.01 * jitterValue * JitterTrackBar.Value * (TrainingTestBorder * 0.9);
+          point.YValues[0] = estimatedValue;
+          point.Tag = new KeyValuePair<double, double>(TestAxisValue, jitterValue);
+          series.Points.Add(point);
+        }
+      }
+
+      UpdateCursorInterval();
+    }
+
+    private void AddThresholds() {
+      chart.Annotations.Clear();
+      int classIndex = 1;
+      foreach (double threshold in Content.Thresholds) {
+        if (!double.IsInfinity(threshold)) {
+          HorizontalLineAnnotation annotation = new HorizontalLineAnnotation();
+          annotation.AllowMoving = true;
+          annotation.AllowResizing = false;
+          annotation.LineWidth = 2;
+          annotation.LineColor = Color.Red;
+
+          annotation.IsInfinitive = true;
+          annotation.ClipToChartArea = chart.ChartAreas[0].Name;
+          annotation.Tag = classIndex;  //save classIndex as Tag to avoid moving the threshold accross class bounderies
+
+          annotation.AxisX = chart.ChartAreas[0].AxisX;
+          annotation.AxisY = chart.ChartAreas[0].AxisY;
+          annotation.Y = threshold;
+
+          chart.Annotations.Add(annotation);
+          classIndex++;
+        }
+      }
+    }
+
+    private void JitterTrackBar_ValueChanged(object sender, EventArgs e) {
+      foreach (Series series in chart.Series) {
+        foreach (DataPoint point in series.Points) {
+          double value = ((KeyValuePair<double, double>)point.Tag).Key;
+          double jitterValue = ((KeyValuePair<double, double>)point.Tag).Value; ;
+          point.XValue = value + 0.01 * jitterValue * JitterTrackBar.Value * (TrainingTestBorder * 0.9);
+        }
+      }
+    }
+
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = series.Points.Count == 0;
+          foreach (LegendCell cell in legendItem.Cells)
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+        }
+      }
+    }
+
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+    }
+
+    private void ToggleSeries(Series series) {
+      if (series.Points.Count == 0)
+        FillSeriesWithDataPoints(series);
+      else
+        series.Points.Clear();
+    }
+
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        if (result.Series != null) ToggleSeries(result.Series);
+      }
+    }
+
+    private void chart_AnnotationPositionChanging(object sender, AnnotationPositionChangingEventArgs e) {
+      int classIndex = (int)e.Annotation.Tag;
+
+      double classValue = Content.ProblemData.SortedClassValues.ElementAt(classIndex);
+      if (e.NewLocationY >= classValue)
+        e.NewLocationY = classValue;
+
+      classValue = Content.ProblemData.SortedClassValues.ElementAt(classIndex - 1);
+      if (e.NewLocationY <= classValue)
+        e.NewLocationY = classValue;
+
+      double[] thresholds = Content.Thresholds.ToArray();
+      thresholds[classIndex] = e.NewLocationY;
+      Content.Thresholds = thresholds;
+    }
+
+    private void UpdateCursorInterval() {
+      Series series = chart.Series[0];
+      double[] xValues = (from point in series.Points
+                          where !point.IsEmpty
+                          select point.XValue)
+                    .DefaultIfEmpty(1.0)
+                    .ToArray();
+      double[] yValues = (from point in series.Points
+                          where !point.IsEmpty
+                          select point.YValues[0])
+                    .DefaultIfEmpty(1.0)
+                    .ToArray();
+
+      double xRange = xValues.Max() - xValues.Min();
+      double yRange = yValues.Max() - yValues.Min();
+      if (xRange.IsAlmost(0.0)) xRange = 1.0;
+      if (yRange.IsAlmost(0.0)) yRange = 1.0;
+      double xDigits = (int)Math.Log10(xRange) - 3;
+      double yDigits = (int)Math.Log10(yRange) - 3;
+      double xZoomInterval = Math.Pow(10, xDigits);
+      double yZoomInterval = Math.Pow(10, yDigits);
+      this.chart.ChartAreas[0].CursorX.Interval = xZoomInterval;
+      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/ClassificationProblemData.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/ClassificationProblemData.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/ClassificationProblemData.cs	(revision 4565)
@@ -0,0 +1,315 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Classification {
+  [Item("ClassificationProblemData", "Represents an item containing all data defining a classification problem.")]
+  [StorableClass]
+  public class ClassificationProblemData : DataAnalysisProblemData {
+    #region default data
+    private static string[] defaultInputs = 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        }
+};
+    #endregion
+
+    private const int MaximumClasses = 20;
+    private const string ClassNamesParameterName = "ClassNames";
+    private const string MisclassificationMatrixParameterName = "MisClassificationMatrix";
+
+    public StringArray ClassNames {
+      get { return ClassNamesParameter.Value; }
+      protected set { ClassNamesParameter.Value = value; }
+    }
+    public IValueParameter<StringArray> ClassNamesParameter {
+      get { return (IValueParameter<StringArray>)Parameters[ClassNamesParameterName]; }
+    }
+
+    public DoubleMatrix MisclassificationMatrix {
+      get { return MisclassificationMatrixParameter.Value; }
+      protected set { MisclassificationMatrixParameter.Value = value; }
+    }
+    public IValueParameter<DoubleMatrix> MisclassificationMatrixParameter {
+      get { return (IValueParameter<DoubleMatrix>)Parameters[MisclassificationMatrixParameterName]; }
+    }
+
+    [Storable]
+    private List<double> sortedClassValues;
+    public IEnumerable<double> SortedClassValues {
+      get { return sortedClassValues; }
+    }
+    public int NumberOfClasses {
+      get { return sortedClassValues.Count; }
+    }
+
+    public ClassificationProblemData()
+      : base(new Dataset(defaultInputs, defaultData), defaultInputs, defaultInputs[defaultInputs.Length - 1], 0, 60, 60, 120) {
+      Parameters.Add(new ValueParameter<StringArray>(ClassNamesParameterName, "An array of the names for all class values."));
+      Parameters.Add(new ValueParameter<DoubleMatrix>(MisclassificationMatrixParameterName, "A matrix that describles the penalties for misclassifaction between the single classes."));
+      sortedClassValues = new List<double>();
+
+      InputVariables.SetItemCheckedState(InputVariables[InputVariables.Count - 1], false);
+      RegisterParameterEvents();
+      UpdateClassValues();
+    }
+
+    [StorableConstructor]
+    protected ClassificationProblemData(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      RegisterParameterEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      ClassificationProblemData clone = (ClassificationProblemData)base.Clone(cloner);
+      clone.RegisterParameterEvents();
+      clone.UpdateClassValues();
+      return clone;
+    }
+
+    protected override void OnProblemDataChanged(System.EventArgs e) {
+      if (!suppressEvents) {
+        UpdateClassValues();
+        base.OnProblemDataChanged(e);
+      }
+    }
+
+    public override void ImportFromFile(string fileName) {
+      var csvFileParser = new CsvFileParser();
+      csvFileParser.Parse(fileName);
+      suppressEvents = true;
+      Name = "Data imported from " + Path.GetFileName(fileName);
+      Dataset = new Dataset(csvFileParser.VariableNames, csvFileParser.Values);
+      Dataset.Name = Path.GetFileName(fileName);
+      var variableNames = Dataset.VariableNames.Select(x => new StringValue(x).AsReadOnly()).ToList();
+      var validTargetVariables = variableNames.Select(variable => new { Variable = variable, DistinctValues = Dataset.GetVariableValues(variable.Value, 0, 50).Distinct().Count() })
+         .OrderBy(x => x.DistinctValues).Where(x => x.DistinctValues <= MaximumClasses).Select(x => x.Variable);
+      if (!validTargetVariables.Any())
+        throw new ArgumentException("Import of classification problem data was not successfull, because no target variable was found." +
+          " A target varialbe must have at most " + MaximumClasses + " distinct values to be applicable to classification.");
+
+      ((ConstrainedValueParameter<StringValue>)TargetVariableParameter).ValidValues.Clear();
+      foreach (var variableName in validTargetVariables)
+        ((ConstrainedValueParameter<StringValue>)TargetVariableParameter).ValidValues.Add(variableName);
+      TargetVariable = validTargetVariables.FirstOrDefault();
+
+      InputVariables = new CheckedItemList<StringValue>(variableNames).AsReadOnly();
+      InputVariables.SetItemCheckedState(validTargetVariables.First(), false);
+      int middle = (int)(csvFileParser.Rows * 0.5);
+      TrainingSamplesStart = new IntValue(0);
+      TrainingSamplesEnd = new IntValue(middle);
+      TestSamplesStart = new IntValue(middle);
+      TestSamplesEnd = new IntValue(csvFileParser.Rows);
+      suppressEvents = false;
+      OnProblemDataChanged(EventArgs.Empty);
+    }
+
+    private void UpdateClassValues() {
+      sortedClassValues = Dataset.GetVariableValues(TargetVariable.Value).Distinct().ToList();
+      sortedClassValues.Sort();
+      ResetMisclassificationMatrix();
+      UpdateClassNames();
+    }
+
+    private void UpdateClassNames() {
+      if (ClassNames != null) DeregisterParameterValueEvents();
+      StringArray array = new StringArray(NumberOfClasses);
+      int i = 0;
+      foreach (double classValue in SortedClassValues) {
+        array[i] = "Class " + classValue;
+        i++;
+      }
+      ClassNames = array;
+      RegisterParameterValueEvents();
+    }
+
+    private void RegisterParameterEvents() {
+      ClassNamesParameter.ValueChanged += new EventHandler(ClassNamesChanged);
+    }
+    private void RegisterParameterValueEvents() {
+      ClassNames.ItemChanged += new EventHandler<EventArgs<int>>(ClassNamesChanged);
+    }
+    private void DeregisterParameterValueEvents() {
+      ClassNames.ItemChanged -= new EventHandler<EventArgs<int>>(ClassNamesChanged);
+    }
+
+    private void ClassNamesChanged(object sender, EventArgs e) {
+      UpdateMisclassifciationMatrixHeaders();
+    }
+
+    private void ResetMisclassificationMatrix() {
+      double[,] matrix = new double[NumberOfClasses, NumberOfClasses];
+      for (int i = 0; i < NumberOfClasses; i++) {
+        for (int j = 0; j < NumberOfClasses; j++)
+          if (i != j) matrix[i, j] = 1;
+      }
+
+      if (MisclassificationMatrix == null)
+        MisclassificationMatrix = new DoubleMatrix(matrix);
+      if (MisclassificationMatrix.Rows != NumberOfClasses)
+        MisclassificationMatrix = new DoubleMatrix(matrix);
+      if (MisclassificationMatrix.Columns != NumberOfClasses)
+        MisclassificationMatrix = new DoubleMatrix(matrix);
+    }
+
+    private void UpdateMisclassifciationMatrixHeaders() {
+      MisclassificationMatrix.RowNames = ClassNames.Select(name => "Estimated " + name);
+      MisclassificationMatrix.ColumnNames = ClassNames.Select(name => "Actual " + name);
+    }
+
+
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj	(revision 4565)
@@ -0,0 +1,201 @@
+﻿<?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>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Problems.DataAnalysis.Classification</RootNamespace>
+    <AssemblyName>HeuristicLab.Problems.DataAnalysis.Classification-3.3</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.Problems.DataAnalysis.Classification-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.Problems.DataAnalysis.Classification-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.Problems.DataAnalysis.Classification-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.Problems.DataAnalysis.Classification-3.3.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Data" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ClassificationProblemData.cs" />
+    <Compile Include="HeuristicLabProblemsDataAnalysisClassificationPlugin.cs" />
+    <Compile Include="Interfaces\IClassificationSolution.cs" />
+    <Compile Include="SingleObjectiveClassificationProblem.cs" />
+    <Compile Include="Interfaces\ISymbolicClassificationEvaluator.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Interfaces\ISymbolicClassificationAnalyzer.cs" />
+    <Compile Include="Symbolic\Analyzer\ValidationBestSymbolicClassificationSolutionAnalyzer.cs" />
+    <Compile Include="Symbolic\Evaluators\OnlineAccuracyEvaluator.cs" />
+    <Compile Include="Symbolic\Evaluators\SymbolicClassificationPearsonRSquaredEvaluator.cs" />
+    <Compile Include="Symbolic\SymbolicClassificationSolution.cs" />
+    <Compile Include="Symbolic\Evaluators\SymbolicClassificationMeanSquaredErrorEvaluator.cs" />
+    <Compile Include="Symbolic\SymbolicClassificationProblem.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLabProblemsDataAnalysisClassificationPlugin.cs.frame" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+    </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>
+    </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>
+    </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>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding\3.3\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.3.csproj">
+      <Project>{125D3006-67F5-48CB-913E-73C0548F17FA}</Project>
+      <Name>HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
+      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
+      <Name>HeuristicLab.Operators-3.3</Name>
+    </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>
+    </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>
+    </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>
+    </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>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis.Regression\3.3\HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj">
+      <Project>{BDF86B1D-630E-4CE2-8A49-8C90B1BDE4C9}</Project>
+      <Name>HeuristicLab.Problems.DataAnalysis.Regression-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.DataAnalysis\3.3\HeuristicLab.Problems.DataAnalysis-3.3.csproj">
+      <Project>{70DFD984-B1D9-46FE-8EB7-4DE92D71A9FC}</Project>
+      <Name>HeuristicLab.Problems.DataAnalysis-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+SubWCRev "%25ProjectDir%25\" "%25ProjectDir%25HeuristicLabProblemsDataAnalysisClassificationPlugin.cs.frame" "%25ProjectDir%25\HeuristicLabProblemsDataAnalysisClassificationPlugin.cs"</PreBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLabProblemsDataAnalysisClassificationPlugin.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLabProblemsDataAnalysisClassificationPlugin.cs.frame	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLabProblemsDataAnalysisClassificationPlugin.cs.frame	(revision 4565)
@@ -0,0 +1,41 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  [Plugin("HeuristicLab.Problems.DataAnalysis.Classification", "3.3.1.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.DataAnalysis.Classification-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Analysis", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis.Regression", "3.3")]
+  public class HeuristicLabProblemsDataAnalysisClassificationPlugin : PluginBase {
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/IClassificationSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/IClassificationSolution.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/IClassificationSolution.cs	(revision 4565)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Classification {
+  public interface IClassificationSolution : IItem {
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/ISymbolicClassificationAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/ISymbolicClassificationAnalyzer.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/ISymbolicClassificationAnalyzer.cs	(revision 4565)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Problems.DataAnalysis.Regression.Symbolic.Analyzers;
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  public interface ISymbolicClassificationAnalyzer : ISymbolicRegressionAnalyzer {
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/ISymbolicClassificationEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/ISymbolicClassificationEvaluator.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Interfaces/ISymbolicClassificationEvaluator.cs	(revision 4565)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Problems.DataAnalysis.Regression.Symbolic;
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  public interface ISymbolicClassificationEvaluator : ISymbolicRegressionEvaluator {
+    ClassificationProblemData ClassificationProblemData { get; }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Properties/AssemblyInfo.frame
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Properties/AssemblyInfo.frame	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Properties/AssemblyInfo.frame	(revision 4565)
@@ -0,0 +1,55 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Classification")]
+[assembly: AssemblyDescription("HeuristicLab DataAnalysis Classification")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2010 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("81f6afd4-4c1f-4867-8c11-726e242dd7cb")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("3.3.1.0")]
+[assembly: AssemblyFileVersion("3.3.1.$WCREV$")]
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/SingleObjectiveClassificationProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/SingleObjectiveClassificationProblem.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/SingleObjectiveClassificationProblem.cs	(revision 4565)
@@ -0,0 +1,90 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Classification {
+  [Item("Classification Problem", "Represents a classfication problem.")]
+  [StorableClass]
+  public abstract class SingleObjectiveClassificationProblem<T, U> : SingleObjectiveProblem<T, U>, ISingleObjectiveDataAnalysisProblem
+    where T : class, ISingleObjectiveEvaluator
+    where U : class, ISolutionCreator {
+    private const string ClassificationProblemDataParameterName = "ClassificationProblemData";
+
+    public IValueParameter<ClassificationProblemData> ClassificationProblemDataParameter {
+      get { return (IValueParameter<ClassificationProblemData>)Parameters[ClassificationProblemDataParameterName]; }
+    }
+    public ClassificationProblemData ClassificationProblemData {
+      get { return ClassificationProblemDataParameter.Value; }
+      set { ClassificationProblemDataParameter.Value = value; }
+    }
+
+    DataAnalysisProblemData IDataAnalysisProblem.DataAnalysisProblemData {
+      get { return ClassificationProblemData; }
+    }
+
+    [StorableConstructor]
+    protected SingleObjectiveClassificationProblem(bool deserializing) : base(deserializing) { }
+    public SingleObjectiveClassificationProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<ClassificationProblemData>(ClassificationProblemDataParameterName, "The data set, target variable and input variables of the data analysis problem."));
+      ClassificationProblemData = new ClassificationProblemData();
+      RegisterParameterEvents();
+      RegisterParameterValueEvents();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserializationHook() {
+      RegisterParameterEvents();
+      RegisterParameterValueEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      SingleObjectiveClassificationProblem<T, U> clone = (SingleObjectiveClassificationProblem<T, U>)base.Clone(cloner);
+      clone.RegisterParameterEvents();
+      clone.RegisterParameterValueEvents();
+      return clone;
+    }
+
+    private void RegisterParameterEvents() {
+      ClassificationProblemDataParameter.ValueChanged += new EventHandler(ClassificationProblemDataParameter_ValueChanged);
+    }
+    private void RegisterParameterValueEvents() {
+      ClassificationProblemData.ProblemDataChanged += new EventHandler(ClassificationProblemData_ProblemDataChanged);
+    }
+
+    protected virtual void OnClassificationProblemDataChanged() {
+      OnReset();
+    }
+    private void ClassificationProblemDataParameter_ValueChanged(object sender, System.EventArgs e) {
+      RegisterParameterValueEvents();
+      OnClassificationProblemDataChanged();
+    }
+    private void ClassificationProblemData_ProblemDataChanged(object sender, System.EventArgs e) {
+      OnClassificationProblemDataChanged();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Analyzer/ValidationBestSymbolicClassificationSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Analyzer/ValidationBestSymbolicClassificationSolutionAnalyzer.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Analyzer/ValidationBestSymbolicClassificationSolutionAnalyzer.cs	(revision 4565)
@@ -0,0 +1,308 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic.Analyzers;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  [Item("ValidationBestSymbolicClassificationSolutionAnalyzer", "An operator that analyzes the validation best symbolic classification solution.")]
+  [StorableClass]
+  public class ValidationBestSymbolicClassificationSolutionAnalyzer : SingleSuccessorOperator, ISymbolicClassificationAnalyzer {
+    private const string MaximizationParameterName = "Maximization";
+    private const string GenerationsParameterName = "Generations";
+    private const string RandomParameterName = "Random";
+    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
+    private const string SymbolicExpressionTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+
+    private const string ClassificationProblemDataParameterName = "ClassificationProblemData";
+    private const string EvaluatorParameterName = "Evaluator";
+    private const string ValidationSamplesStartParameterName = "SamplesStart";
+    private const string ValidationSamplesEndParameterName = "SamplesEnd";
+    private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
+    private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
+    private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
+
+    private const string ResultsParameterName = "Results";
+    private const string BestValidationQualityParameterName = "Best validation quality";
+    private const string BestValidationSolutionParameterName = "Best validation solution";
+    private const string BestSolutionAccuracyTrainingParameterName = "Best solution accuracy (training)";
+    private const string BestSolutionAccuracyTestParameterName = "Best solution accuracy (test)";
+    private const string VariableFrequenciesParameterName = "VariableFrequencies";
+
+    #region parameter properties
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters[MaximizationParameterName]; }
+    }
+    public ILookupParameter<IntValue> GenerationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters[GenerationsParameterName]; }
+    }
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
+    }
+    public ScopeTreeLookupParameter<SymbolicExpressionTree> SymbolicExpressionTreeParameter {
+      get { return (ScopeTreeLookupParameter<SymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
+    }
+    public IValueLookupParameter<ISymbolicExpressionTreeInterpreter> SymbolicExpressionTreeInterpreterParameter {
+      get { return (IValueLookupParameter<ISymbolicExpressionTreeInterpreter>)Parameters[SymbolicExpressionTreeInterpreterParameterName]; }
+    }
+
+    public ILookupParameter<ClassificationProblemData> ClassificationProblemDataParameter {
+      get { return (ILookupParameter<ClassificationProblemData>)Parameters[ClassificationProblemDataParameterName]; }
+    }
+    public ILookupParameter<ISymbolicClassificationEvaluator> EvaluatorParameter {
+      get { return (ILookupParameter<ISymbolicClassificationEvaluator>)Parameters[EvaluatorParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> ValidationSamplesStartParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[ValidationSamplesStartParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> ValidationSamplesEndParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[ValidationSamplesEndParameterName]; }
+    }
+    public IValueParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
+      get { return (IValueParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> UpperEstimationLimitParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[UpperEstimationLimitParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> LowerEstimationLimitParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[LowerEstimationLimitParameterName]; }
+    }
+    public ILookupParameter<DataTable> VariableFrequenciesParameter {
+      get { return (ILookupParameter<DataTable>)Parameters[VariableFrequenciesParameterName]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
+    }
+    public ILookupParameter<DoubleValue> BestValidationQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[BestValidationQualityParameterName]; }
+    }
+    public ILookupParameter<SymbolicClassificationSolution> BestValidationSolutionParameter {
+      get { return (ILookupParameter<SymbolicClassificationSolution>)Parameters[BestValidationSolutionParameterName]; }
+    }
+    public ILookupParameter<DoubleValue> BestSolutionAccuracyTrainingParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[BestSolutionAccuracyTrainingParameterName]; }
+    }
+    public ILookupParameter<DoubleValue> BestSolutionAccuracyTestParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[BestSolutionAccuracyTestParameterName]; }
+    }
+    #endregion
+    #region properties
+    public BoolValue Maximization {
+      get { return MaximizationParameter.ActualValue; }
+    }
+    public IntValue Generations {
+      get { return GenerationsParameter.ActualValue; }
+    }
+    public IRandom Random {
+      get { return RandomParameter.ActualValue; }
+    }
+    public ItemArray<SymbolicExpressionTree> SymbolicExpressionTree {
+      get { return SymbolicExpressionTreeParameter.ActualValue; }
+    }
+    public ISymbolicExpressionTreeInterpreter SymbolicExpressionTreeInterpreter {
+      get { return SymbolicExpressionTreeInterpreterParameter.ActualValue; }
+    }
+
+    public ClassificationProblemData ClassificationProblemData {
+      get { return ClassificationProblemDataParameter.ActualValue; }
+    }
+    public ISymbolicClassificationEvaluator Evaluator {
+      get { return EvaluatorParameter.ActualValue; }
+    }
+    public IntValue ValidiationSamplesStart {
+      get { return ValidationSamplesStartParameter.ActualValue; }
+    }
+    public IntValue ValidationSamplesEnd {
+      get { return ValidationSamplesEndParameter.ActualValue; }
+    }
+    public PercentValue RelativeNumberOfEvaluatedSamples {
+      get { return RelativeNumberOfEvaluatedSamplesParameter.Value; }
+    }
+    public DoubleValue UpperEstimationLimit {
+      get { return UpperEstimationLimitParameter.ActualValue; }
+    }
+    public DoubleValue LowerEstimationLimit {
+      get { return LowerEstimationLimitParameter.ActualValue; }
+    }
+    public DataTable VariableFrequencies {
+      get { return VariableFrequenciesParameter.ActualValue; }
+    }
+
+    public ResultCollection Results {
+      get { return ResultsParameter.ActualValue; }
+    }
+    public DoubleValue BestValidationQuality {
+      get { return BestValidationQualityParameter.ActualValue; }
+      protected set { BestValidationQualityParameter.ActualValue = value; }
+    }
+    public SymbolicClassificationSolution BestValidationSolution {
+      get { return BestValidationSolutionParameter.ActualValue; }
+      protected set { BestValidationSolutionParameter.ActualValue = value; }
+    }
+    public DoubleValue BestSolutionAccuracyTraining {
+      get { return BestSolutionAccuracyTrainingParameter.ActualValue; }
+      protected set { BestSolutionAccuracyTrainingParameter.ActualValue = value; }
+    }
+    public DoubleValue BestSolutionAccuracyTest {
+      get { return BestSolutionAccuracyTestParameter.ActualValue; }
+      protected set { BestSolutionAccuracyTestParameter.ActualValue = value; }
+    }
+    #endregion
+
+    public ValidationBestSymbolicClassificationSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>(MaximizationParameterName, "The direction of optimization."));
+      Parameters.Add(new LookupParameter<IntValue>(GenerationsParameterName, "The number of generations calculated so far."));
+      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "The random generator to use."));
+      Parameters.Add(new ScopeTreeLookupParameter<SymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression trees to analyze."));
+      Parameters.Add(new ValueLookupParameter<ISymbolicExpressionTreeInterpreter>(SymbolicExpressionTreeInterpreterParameterName, "The interpreter that should be used for the analysis of symbolic expression trees."));
+
+      Parameters.Add(new LookupParameter<ClassificationProblemData>(ClassificationProblemDataParameterName, "The problem data for which the symbolic expression tree is a solution."));
+      Parameters.Add(new LookupParameter<ISymbolicClassificationEvaluator>(EvaluatorParameterName, "The evaluator which should be used to evaluate the solution on the validation set."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(ValidationSamplesStartParameterName, "The first index of the validation partition of the data set."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(ValidationSamplesEndParameterName, "The last index of the validation partition of the data set."));
+      Parameters.Add(new ValueParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.", new PercentValue(1)));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(UpperEstimationLimitParameterName, "The upper estimation limit that was set for the evaluation of the symbolic expression trees."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(LowerEstimationLimitParameterName, "The lower estimation limit that was set for the evaluation of the symbolic expression trees."));
+      Parameters.Add(new LookupParameter<DataTable>(VariableFrequenciesParameterName, "The variable frequencies table to use for the calculation of variable impacts"));
+
+      Parameters.Add(new ValueLookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
+      Parameters.Add(new LookupParameter<DoubleValue>(BestValidationQualityParameterName, "The validation quality of the best solution in the current run."));
+      Parameters.Add(new LookupParameter<SymbolicClassificationSolution>(BestValidationSolutionParameterName, "The best solution on the validation data found in the current run."));
+      Parameters.Add(new LookupParameter<DoubleValue>(BestSolutionAccuracyTrainingParameterName, "The training accuracy of the best solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>(BestSolutionAccuracyTestParameterName, "The test accuracy of the best solution."));
+    }
+
+    [StorableConstructor]
+    private ValidationBestSymbolicClassificationSolutionAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public override IOperation Apply() {
+      var trees = SymbolicExpressionTree;
+      string targetVariable = ClassificationProblemData.TargetVariable.Value;
+
+      // select a random subset of rows in the validation set
+      int validationStart = ValidiationSamplesStart.Value;
+      int validationEnd = ValidationSamplesEnd.Value;
+      int seed = Random.Next();
+      int count = (int)((validationEnd - validationStart) * RelativeNumberOfEvaluatedSamples.Value);
+      if (count == 0) count = 1;
+      IEnumerable<int> rows = RandomEnumerable.SampleRandomNumbers(seed, validationStart, validationEnd, count)
+         .Where(row => row < ClassificationProblemData.TestSamplesStart.Value || ClassificationProblemData.TestSamplesEnd.Value <= row);
+
+      double upperEstimationLimit = UpperEstimationLimit != null ? UpperEstimationLimit.Value : double.PositiveInfinity;
+      double lowerEstimationLimit = LowerEstimationLimit != null ? LowerEstimationLimit.Value : double.NegativeInfinity;
+
+      double bestQuality = Maximization.Value ? double.NegativeInfinity : double.PositiveInfinity;
+      SymbolicExpressionTree bestTree = null;
+
+      foreach (var tree in trees) {
+        double quality = Evaluator.Evaluate(SymbolicExpressionTreeInterpreter, tree,
+          lowerEstimationLimit, upperEstimationLimit, ClassificationProblemData.Dataset,
+          targetVariable, rows);
+
+        if ((Maximization.Value && quality > bestQuality) ||
+            (!Maximization.Value && quality < bestQuality)) {
+          bestQuality = quality;
+          bestTree = tree;
+        }
+      }
+
+      // if the best validation tree is better than the current best solution => update
+      bool newBest =
+        BestValidationQuality == null ||
+        (Maximization.Value && bestQuality > BestValidationQuality.Value) ||
+        (!Maximization.Value && bestQuality < BestValidationQuality.Value);
+      if (newBest) {
+        double alpha, beta;
+        SymbolicRegressionScaledMeanSquaredErrorEvaluator.Calculate(SymbolicExpressionTreeInterpreter, bestTree,
+          lowerEstimationLimit, upperEstimationLimit,
+          ClassificationProblemData.Dataset, targetVariable,
+          ClassificationProblemData.TrainingIndizes, out beta, out alpha);
+
+        // scale tree for solution
+        var scaledTree = SymbolicRegressionSolutionLinearScaler.Scale(bestTree, alpha, beta);
+        var model = new SymbolicRegressionModel((ISymbolicExpressionTreeInterpreter)SymbolicExpressionTreeInterpreter.Clone(),
+          scaledTree);
+
+        if (BestValidationSolution == null) {
+          BestValidationSolution = new SymbolicClassificationSolution(ClassificationProblemData, model, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
+          BestValidationSolution.Name = BestValidationSolutionParameterName;
+          BestValidationSolution.Description = "Best solution on validation partition found over the whole run.";
+          BestValidationQuality = new DoubleValue(bestQuality);
+        } else {
+          BestValidationSolution.Model = model;
+        }
+
+        UpdateBestSolutionResults();
+      }
+      return base.Apply();
+    }
+
+    private void UpdateBestSolutionResults() {
+      BestSymbolicRegressionSolutionAnalyzer.UpdateBestSolutionResults(BestValidationSolution, ClassificationProblemData, Results, Generations, VariableFrequencies);
+
+      IEnumerable<double> trainingValues = ClassificationProblemData.Dataset.GetEnumeratedVariableValues(
+        ClassificationProblemData.TargetVariable.Value, ClassificationProblemData.TrainingIndizes);
+      IEnumerable<double> testValues = ClassificationProblemData.Dataset.GetEnumeratedVariableValues(
+        ClassificationProblemData.TargetVariable.Value, ClassificationProblemData.TestIndizes);
+
+      OnlineAccuracyEvaluator accuracyEvaluator = new OnlineAccuracyEvaluator();
+      var originalEnumerator = trainingValues.GetEnumerator();
+      var estimatedEnumerator = BestValidationSolution.EstimatedTrainingClassValues.GetEnumerator();
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        accuracyEvaluator.Add(originalEnumerator.Current, estimatedEnumerator.Current);
+      }
+      double trainingAccuracy = accuracyEvaluator.Accuracy;
+
+      accuracyEvaluator.Reset();
+      originalEnumerator = testValues.GetEnumerator();
+      estimatedEnumerator = BestValidationSolution.EstimatedTestClassValues.GetEnumerator();
+      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
+        accuracyEvaluator.Add(originalEnumerator.Current, estimatedEnumerator.Current);
+      }
+      double testAccuracy = accuracyEvaluator.Accuracy;
+
+      if (!Results.ContainsKey(BestSolutionAccuracyTrainingParameterName)) {
+        BestSolutionAccuracyTraining = new DoubleValue(trainingAccuracy);
+        BestSolutionAccuracyTest = new DoubleValue(testAccuracy);
+
+        Results.Add(new Result(BestSolutionAccuracyTrainingParameterName, BestSolutionAccuracyTraining));
+        Results.Add(new Result(BestSolutionAccuracyTestParameterName, BestSolutionAccuracyTest));
+      } else {
+        BestSolutionAccuracyTraining.Value = trainingAccuracy;
+        BestSolutionAccuracyTest.Value = testAccuracy;
+      }
+    }
+
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/OnlineAccuracyEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/OnlineAccuracyEvaluator.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/OnlineAccuracyEvaluator.cs	(revision 4565)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  public class OnlineAccuracyEvaluator : IOnlineEvaluator {
+    private int n;
+    private int correctClassified; // TP + TN necessary for multi class classification
+
+    public OnlineAccuracyEvaluator() {
+      Reset();
+    }
+
+    public void Add(double original, double estimated) {
+      if (double.IsNaN(estimated) || double.IsInfinity(estimated) ||
+          double.IsNaN(original) || double.IsInfinity(original))
+        throw new ArgumentException("Accuracy is not defined for NaN or infinity elements");
+
+      if (original.IsAlmost(estimated))
+        correctClassified++;
+      n++;
+    }
+
+    public void Reset() {
+      n = 0;
+      correctClassified = 0;
+    }
+
+    public double Accuracy {
+      get {
+        if (n < 1)
+          throw new InvalidOperationException("No elements");
+        else
+          return ((double)correctClassified) / n;
+      }
+    }
+    public double Value {
+      get { return Accuracy; }
+    }
+
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/SymbolicClassificationMeanSquaredErrorEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/SymbolicClassificationMeanSquaredErrorEvaluator.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/SymbolicClassificationMeanSquaredErrorEvaluator.cs	(revision 4565)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  [Item("SymbolicClassificationMeanSquaredErrorEvaluator", "Calculates the mean squared error of a symbolic classification solution.")]
+  [StorableClass]
+  public class SymbolicClassifacitionMeanSquaredErrorEvaluator : SymbolicRegressionMeanSquaredErrorEvaluator, ISymbolicClassificationEvaluator {
+    public ClassificationProblemData ClassificationProblemData {
+      get { return (ClassificationProblemData)RegressionProblemData; }
+    }
+
+    public SymbolicClassifacitionMeanSquaredErrorEvaluator()
+      : base() {
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/SymbolicClassificationPearsonRSquaredEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/SymbolicClassificationPearsonRSquaredEvaluator.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/SymbolicClassificationPearsonRSquaredEvaluator.cs	(revision 4565)
@@ -0,0 +1,38 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  [Item("SymbolicClassificationPearsonRSquaredEvaluator", "Calculates the pearson R² correlation coefficient of a symbolic classification solution.")]
+  [StorableClass]
+  public class SymbolicClassificationPearsonRSquaredEvaluator : SymbolicRegressionPearsonsRSquaredEvaluator, ISymbolicClassificationEvaluator {
+    public ClassificationProblemData ClassificationProblemData {
+      get { return (ClassificationProblemData)RegressionProblemData; }
+    }
+
+    public SymbolicClassificationPearsonRSquaredEvaluator()
+      : base() {
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationProblem.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationProblem.cs	(revision 4565)
@@ -0,0 +1,321 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Analyzers;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Creators;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Interfaces;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Symbols;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic.Analyzers;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  [Item("Classification Problem", "Represents a classfication problem.")]
+  [StorableClass]
+  [Creatable("Problems")]
+  public class SymbolicClassificationProblem : SingleObjectiveClassificationProblem<ISymbolicClassificationEvaluator, ISymbolicExpressionTreeCreator>, IStorableContent {
+    private const string SymbolicExpressionTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+    private const string FunctionTreeGrammarParameterName = "FunctionTreeGrammar";
+    private const string MaxExpressionLengthParameterName = "MaxExpressionLength";
+    private const string MaxExpressionDepthParameterName = "MaxExpressionDepth";
+    private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
+    private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
+    private const string MaxFunctionDefiningBranchensParameterName = "MaxFunctionDefiningBranches";
+    private const string MaxFunctionArgumentsParameterName = "MaxFunctionArguments";
+
+    #region properties
+    public string Filename { get; set; }
+
+    public ISymbolicExpressionTreeInterpreter SymbolicExpressionTreeInterpreter {
+      get { return SymbolicExpressionTreeInterpreterParameter.Value; }
+      protected set { SymbolicExpressionTreeInterpreterParameter.Value = value; }
+    }
+    public IValueParameter<ISymbolicExpressionTreeInterpreter> SymbolicExpressionTreeInterpreterParameter {
+      get { return (IValueParameter<ISymbolicExpressionTreeInterpreter>)Parameters[SymbolicExpressionTreeInterpreterParameterName]; }
+    }
+
+    public ISymbolicExpressionGrammar FunctionTreeGrammar {
+      get { return (ISymbolicExpressionGrammar)FunctionTreeGrammarParameter.Value; }
+      protected set { FunctionTreeGrammarParameter.Value = value; }
+    }
+    public IValueParameter<ISymbolicExpressionGrammar> FunctionTreeGrammarParameter {
+      get { return (IValueParameter<ISymbolicExpressionGrammar>)Parameters[FunctionTreeGrammarParameterName]; }
+    }
+
+    public IntValue MaxExpressionLength {
+      get { return MaxExpressionLengthParameter.Value; }
+      protected set { MaxExpressionLengthParameter.Value = value; }
+    }
+    public IValueParameter<IntValue> MaxExpressionLengthParameter {
+      get { return (IValueParameter<IntValue>)Parameters[MaxExpressionLengthParameterName]; }
+    }
+
+    public IntValue MaxExpressionDepth {
+      get { return MaxExpressionDepthParameter.Value; }
+      protected set { MaxExpressionDepthParameter.Value = value; }
+    }
+    public ValueParameter<IntValue> MaxExpressionDepthParameter {
+      get { return (ValueParameter<IntValue>)Parameters[MaxExpressionDepthParameterName]; }
+    }
+
+    public DoubleValue UpperEstimationLimit {
+      get { return UpperEstimationLimitParameter.Value; }
+      protected set { UpperEstimationLimitParameter.Value = value; }
+    }
+    public IValueParameter<DoubleValue> UpperEstimationLimitParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters[UpperEstimationLimitParameterName]; }
+    }
+
+    public DoubleValue LowerEstimationLimit {
+      get { return LowerEstimationLimitParameter.Value; }
+      protected set { LowerEstimationLimitParameter.Value = value; }
+    }
+    public IValueParameter<DoubleValue> LowerEstimationLimitParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters[LowerEstimationLimitParameterName]; }
+    }
+
+    public IntValue MaxFunctionDefiningBranches {
+      get { return MaxFunctionDefiningBranchesParameter.Value; }
+      protected set { MaxFunctionDefiningBranchesParameter.Value = value; }
+    }
+    public IValueParameter<IntValue> MaxFunctionDefiningBranchesParameter {
+      get { return (IValueParameter<IntValue>)Parameters[MaxFunctionDefiningBranchensParameterName]; }
+    }
+
+    public IntValue MaxFunctionArguments {
+      get { return MaxFunctionArgumentsParameter.Value; }
+      protected set { MaxFunctionArgumentsParameter.Value = value; }
+    }
+    public IValueParameter<IntValue> MaxFunctionArgumentsParameter {
+      get { return (IValueParameter<IntValue>)Parameters[MaxFunctionArgumentsParameterName]; }
+    }
+
+    public DoubleValue PunishmentFactor {
+      get { return new DoubleValue(10.0); }
+    }
+    public IntValue TrainingSamplesStart { get { return new IntValue(ClassificationProblemData.TrainingSamplesStart.Value); } }
+    public IntValue TrainingSamplesEnd {
+      get { return new IntValue((ClassificationProblemData.TrainingSamplesStart.Value + ClassificationProblemData.TrainingSamplesEnd.Value) / 2); }
+    }
+    public IntValue ValidationSamplesStart { get { return TrainingSamplesEnd; } }
+    public IntValue ValidationSamplesEnd { get { return new IntValue(ClassificationProblemData.TrainingSamplesEnd.Value); } }
+    public IntValue TestSamplesStart { get { return ClassificationProblemData.TestSamplesStart; } }
+    public IntValue TestSamplesEnd { get { return ClassificationProblemData.TestSamplesEnd; } }
+    #endregion
+
+    [StorableConstructor]
+    protected SymbolicClassificationProblem(bool deserializing) : base(deserializing) { }
+    public SymbolicClassificationProblem()
+      : base() {
+      Parameters.Add(new ValueParameter<ISymbolicExpressionTreeInterpreter>(SymbolicExpressionTreeInterpreterParameterName, "The interpreter that should be used to evaluate the symbolic expression tree."));
+      Parameters.Add(new ValueParameter<ISymbolicExpressionGrammar>(FunctionTreeGrammarParameterName, "The grammar that should be used for symbolic regression models."));
+      Parameters.Add(new ValueParameter<IntValue>(MaxExpressionLengthParameterName, "Maximal length of the symbolic expression."));
+      Parameters.Add(new ValueParameter<IntValue>(MaxExpressionDepthParameterName, "Maximal depth of the symbolic expression."));
+      Parameters.Add(new ValueParameter<DoubleValue>(UpperEstimationLimitParameterName, "The upper limit for the estimated value that can be returned by the symbolic regression model."));
+      Parameters.Add(new ValueParameter<DoubleValue>(LowerEstimationLimitParameterName, "The lower limit for the estimated value that can be returned by the symbolic regression model."));
+      Parameters.Add(new ValueParameter<IntValue>(MaxFunctionDefiningBranchensParameterName, "Maximal number of automatically defined functions."));
+      Parameters.Add(new ValueParameter<IntValue>(MaxFunctionArgumentsParameterName, "Maximal number of arguments of automatically defined functions."));
+
+      SolutionCreator = new ProbabilisticTreeCreator();
+      Evaluator = new SymbolicClassifacitionMeanSquaredErrorEvaluator();
+      ParameterizeSolutionCreator();
+      Maximization = new BoolValue(false);
+      FunctionTreeGrammar = new GlobalSymbolicExpressionGrammar(new FullFunctionalExpressionGrammar());
+      SymbolicExpressionTreeInterpreter = new SimpleArithmeticExpressionInterpreter();
+      MaxExpressionLength = new IntValue(100);
+      MaxExpressionDepth = new IntValue(10);
+      MaxFunctionDefiningBranches = new IntValue(0);
+      MaxFunctionArguments = new IntValue(0);
+
+      InitializeOperators();
+      RegisterParameterEvents();
+
+      UpdateEstimationLimits();
+      ParameterizeEvaluator();
+      ParameterizeSolutionCreator();
+      ParameterizeGrammar();
+      ParameterizeOperators();
+      ParameterizeAnalyzers();
+    }
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+
+    }
+
+    private void RegisterParameterEvents() {
+      SolutionCreator.SymbolicExpressionTreeParameter.ActualNameChanged += new EventHandler(SolutionCreator_SymbolicExpressionTreeParameter_ActualNameChanged);
+      FunctionTreeGrammarParameter.ValueChanged += new EventHandler(FunctionTreeGrammarParameter_ValueChanged);
+
+      MaxFunctionArgumentsParameter.ValueChanged += new EventHandler(ArchitectureParameter_ValueChanged);
+      MaxFunctionDefiningBranchesParameter.ValueChanged += new EventHandler(ArchitectureParameter_ValueChanged);
+      MaxFunctionArgumentsParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
+      MaxFunctionDefiningBranchesParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
+    }
+
+    protected override void OnEvaluatorChanged() {
+      ParameterizeEvaluator();
+      ParameterizeAnalyzers();
+      base.OnEvaluatorChanged();
+    }
+
+    protected override void OnSolutionCreatorChanged() {
+      ParameterizeSolutionCreator();
+      SolutionCreator.SymbolicExpressionTreeParameter.ActualNameChanged += new EventHandler(SolutionCreator_SymbolicExpressionTreeParameter_ActualNameChanged);
+      base.OnSolutionCreatorChanged();
+    }
+    private void SolutionCreator_SymbolicExpressionTreeParameter_ActualNameChanged(object sender, System.EventArgs e) {
+      ParameterizeEvaluator();
+      ParameterizeOperators();
+      ParameterizeAnalyzers();
+    }
+
+    protected override void OnClassificationProblemDataChanged() {
+      ParameterizeAnalyzers();
+      ParameterizeGrammar();
+      ParameterizeEvaluator();
+      UpdateEstimationLimits();
+      base.OnClassificationProblemDataChanged();
+    }
+
+    private void FunctionTreeGrammarParameter_ValueChanged(object sender, System.EventArgs e) {
+      if (!(FunctionTreeGrammar is GlobalSymbolicExpressionGrammar))
+        FunctionTreeGrammar = new GlobalSymbolicExpressionGrammar(FunctionTreeGrammar);
+      OnGrammarChanged();
+    }
+    protected virtual void OnGrammarChanged() {
+      ParameterizeGrammar();
+    }
+
+    private void ArchitectureParameter_ValueChanged(object sender, EventArgs e) {
+      MaxFunctionArgumentsParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
+      MaxFunctionDefiningBranchesParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
+      OnArchitectureParameterChanged();
+    }
+    private void ArchitectureParameterValue_ValueChanged(object sender, EventArgs e) {
+      OnArchitectureParameterChanged();
+    }
+    protected virtual void OnArchitectureParameterChanged() {
+      ParameterizeGrammar();
+    }
+
+    protected virtual void InitializeOperators() {
+      Operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>().OfType<IOperator>());
+      Operators.Add(new MinAverageMaxSymbolicExpressionTreeSizeAnalyzer());
+      Operators.Add(new SymbolicRegressionVariableFrequencyAnalyzer());
+      Operators.Add(new ValidationBestSymbolicClassificationSolutionAnalyzer());
+    }
+
+    #region operator parameterization
+    private void UpdateEstimationLimits() {
+      if (TrainingSamplesStart.Value < TrainingSamplesEnd.Value &&
+        ClassificationProblemData.Dataset.VariableNames.Contains(ClassificationProblemData.TargetVariable.Value)) {
+        var targetValues = ClassificationProblemData.Dataset.GetVariableValues(ClassificationProblemData.TargetVariable.Value, TrainingSamplesStart.Value, TrainingSamplesEnd.Value);
+        var mean = targetValues.Average();
+        var range = targetValues.Max() - targetValues.Min();
+        UpperEstimationLimit = new DoubleValue(mean + PunishmentFactor.Value * range);
+        LowerEstimationLimit = new DoubleValue(mean - PunishmentFactor.Value * range);
+      }
+    }
+
+    private void ParameterizeEvaluator() {
+      if (Evaluator != null) {
+        Evaluator.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+        Evaluator.RegressionProblemDataParameter.ActualName = ClassificationProblemDataParameter.Name;
+        Evaluator.SamplesStartParameter.Value = TrainingSamplesStart;
+        Evaluator.SamplesEndParameter.Value = TrainingSamplesEnd;
+      }
+    }
+
+    private void ParameterizeGrammar() {
+      List<LaggedVariable> laggedSymbols = FunctionTreeGrammar.Symbols.OfType<LaggedVariable>().ToList();
+      foreach (Symbol symbol in laggedSymbols)
+        FunctionTreeGrammar.RemoveSymbol(symbol);
+      foreach (var varSymbol in FunctionTreeGrammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols.Variable>()) {
+        varSymbol.VariableNames = ClassificationProblemData.InputVariables.CheckedItems.Select(x => x.Value.Value);
+      }
+      var globalGrammar = FunctionTreeGrammar as GlobalSymbolicExpressionGrammar;
+      if (globalGrammar != null) {
+        globalGrammar.MaxFunctionArguments = MaxFunctionArguments.Value;
+        globalGrammar.MaxFunctionDefinitions = MaxFunctionDefiningBranches.Value;
+      }
+    }
+
+    private void ParameterizeSolutionCreator() {
+      SolutionCreator.SymbolicExpressionGrammarParameter.ActualName = FunctionTreeGrammarParameter.Name;
+      SolutionCreator.MaxTreeHeightParameter.ActualName = MaxExpressionDepthParameter.Name;
+      SolutionCreator.MaxTreeSizeParameter.ActualName = MaxExpressionLengthParameter.Name;
+      SolutionCreator.MaxFunctionArgumentsParameter.ActualName = MaxFunctionArgumentsParameter.Name;
+      SolutionCreator.MaxFunctionDefinitionsParameter.ActualName = MaxFunctionDefiningBranchesParameter.Name;
+    }
+
+    private void ParameterizeOperators() {
+      foreach (ISymbolicExpressionTreeOperator op in Operators.OfType<ISymbolicExpressionTreeOperator>()) {
+        op.MaxTreeHeightParameter.ActualName = MaxExpressionDepthParameter.Name;
+        op.MaxTreeSizeParameter.ActualName = MaxExpressionLengthParameter.Name;
+        op.SymbolicExpressionGrammarParameter.ActualName = FunctionTreeGrammarParameter.Name;
+      }
+      foreach (ISymbolicExpressionTreeCrossover op in Operators.OfType<ISymbolicExpressionTreeCrossover>()) {
+        op.ParentsParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+        op.ChildParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+      }
+      foreach (ISymbolicExpressionTreeManipulator op in Operators.OfType<ISymbolicExpressionTreeManipulator>()) {
+        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+      }
+      foreach (ISymbolicExpressionTreeArchitectureManipulator op in Operators.OfType<ISymbolicExpressionTreeArchitectureManipulator>()) {
+        op.MaxFunctionArgumentsParameter.ActualName = MaxFunctionArgumentsParameter.Name;
+        op.MaxFunctionDefinitionsParameter.ActualName = MaxFunctionDefiningBranchesParameter.Name;
+      }
+    }
+
+    private void ParameterizeAnalyzers() {
+      foreach (ISymbolicRegressionAnalyzer analyzer in Operators.OfType<ISymbolicRegressionAnalyzer>()) {
+        analyzer.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+        var bestValidationSolutionAnalyzer = analyzer as ValidationBestSymbolicClassificationSolutionAnalyzer;
+        if (bestValidationSolutionAnalyzer != null) {
+          bestValidationSolutionAnalyzer.ClassificationProblemDataParameter.ActualName = ClassificationProblemDataParameter.Name;
+          bestValidationSolutionAnalyzer.UpperEstimationLimitParameter.ActualName = UpperEstimationLimitParameter.Name;
+          bestValidationSolutionAnalyzer.LowerEstimationLimitParameter.ActualName = LowerEstimationLimitParameter.Name;
+          bestValidationSolutionAnalyzer.SymbolicExpressionTreeInterpreterParameter.ActualName = SymbolicExpressionTreeInterpreterParameter.Name;
+          bestValidationSolutionAnalyzer.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
+          bestValidationSolutionAnalyzer.ValidationSamplesStartParameter.Value = ValidationSamplesStart;
+          bestValidationSolutionAnalyzer.ValidationSamplesEndParameter.Value = ValidationSamplesEnd;
+        }
+        var varFreqAnalyzer = analyzer as SymbolicRegressionVariableFrequencyAnalyzer;
+        if (varFreqAnalyzer != null) {
+          varFreqAnalyzer.ProblemDataParameter.ActualName = ClassificationProblemDataParameter.Name;
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationSolution.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationSolution.cs	(revision 4565)
+++ trunk/sources/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationSolution.cs	(revision 4565)
@@ -0,0 +1,163 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+
+namespace HeuristicLab.Problems.DataAnalysis.Classification {
+  /// <summary>
+  /// Represents a solution for a symbolic classification problem which can be visualized in the GUI.
+  /// </summary>
+  [Item("SymbolicClassificationSolution", "Represents a solution for a symbolic classification problem which can be visualized in the GUI.")]
+  [StorableClass]
+  public class SymbolicClassificationSolution : SymbolicRegressionSolution, IClassificationSolution {
+    private SymbolicClassificationSolution() : base() { }
+    public SymbolicClassificationSolution(ClassificationProblemData problemData, SymbolicRegressionModel model, double lowerEstimationLimit, double upperEstimationLimit)
+      : base(problemData, model, lowerEstimationLimit, upperEstimationLimit) {
+    }
+
+    public new ClassificationProblemData ProblemData {
+      get { return (ClassificationProblemData)base.ProblemData; }
+      set { base.ProblemData = value; }
+    }
+
+    protected override void RecalculateEstimatedValues() {
+      estimatedValues =
+          (from x in Model.GetEstimatedValues(ProblemData, 0, ProblemData.Dataset.Rows)
+           let boundedX = Math.Min(UpperEstimationLimit, Math.Max(LowerEstimationLimit, x))
+           select double.IsNaN(boundedX) ? UpperEstimationLimit : boundedX).ToList();
+      RecalculateClassIntermediates();
+      OnEstimatedValuesChanged();
+    }
+
+    private void RecalculateClassIntermediates() {
+      int slices = 100;
+
+      List<int> classInstances = (from classValue in ProblemData.Dataset.GetVariableValues(ProblemData.TargetVariable.Value)
+                                  group classValue by classValue into grouping
+                                  select grouping.Count()).ToList();
+
+      List<KeyValuePair<double, double>> estimatedTargetValues =
+         (from row in ProblemData.TrainingIndizes
+          select new KeyValuePair<double, double>(
+            estimatedValues[row],
+            ProblemData.Dataset[ProblemData.TargetVariable.Value, row])).ToList();
+
+      List<double> originalClasses = ProblemData.SortedClassValues.ToList();
+      double[] thresholds = new double[ProblemData.NumberOfClasses + 1];
+      thresholds[0] = double.NegativeInfinity;
+      thresholds[thresholds.Length - 1] = double.PositiveInfinity;
+
+      for (int i = 1; i < thresholds.Length - 1; i++) {
+        double lowerThreshold = thresholds[i - 1];
+        double actualThreshold = originalClasses[i - 1];
+        double thresholdIncrement = (originalClasses[i] - originalClasses[i - 1]) / slices;
+
+        double bestThreshold = double.NaN;
+        double bestClassificationScore = double.PositiveInfinity;
+
+        while (actualThreshold < originalClasses[i]) {
+          double classificationScore = 0.0;
+
+          foreach (KeyValuePair<double, double> estimatedTarget in estimatedTargetValues) {
+            //all positives
+            if (estimatedTarget.Value.IsAlmost(originalClasses[i - 1])) {
+              if (estimatedTarget.Key > lowerThreshold && estimatedTarget.Key < actualThreshold)
+                //true positive
+                classificationScore += ProblemData.MisclassificationMatrix[i - 1, i - 1] / classInstances[i - 1];
+              else
+                //false negative
+                classificationScore += ProblemData.MisclassificationMatrix[i, i - 1] / classInstances[i - 1];
+            }
+              //all negatives
+            else {
+              if (estimatedTarget.Key > lowerThreshold && estimatedTarget.Key < actualThreshold)
+                classificationScore += ProblemData.MisclassificationMatrix[i - 1, i] / classInstances[i];
+              else
+                //true negative, consider only upper class
+                classificationScore += ProblemData.MisclassificationMatrix[i, i] / classInstances[i];
+            }
+          }
+          if (classificationScore < bestClassificationScore) {
+            bestClassificationScore = classificationScore;
+            bestThreshold = actualThreshold;
+          }
+          actualThreshold += thresholdIncrement;
+        }
+        thresholds[i] = bestThreshold;
+      }
+      this.optimalThresholds = new List<double>(thresholds);
+      this.actualThresholds = optimalThresholds;
+    }
+
+    #region properties
+    private List<double> optimalThresholds;
+    private List<double> actualThresholds;
+    public IEnumerable<double> Thresholds {
+      get {
+        if (actualThresholds == null) RecalculateEstimatedValues();
+        return actualThresholds;
+      }
+      set {
+        if (actualThresholds != null && actualThresholds.SequenceEqual(value))
+          return;
+        actualThresholds = new List<double>(value);
+        OnThresholdsChanged();
+      }
+    }
+
+    public IEnumerable<double> EstimatedClassValues {
+      get { return GetEstimatedClassValues(Enumerable.Range(0, ProblemData.Dataset.Rows)); }
+    }
+
+    public IEnumerable<double> EstimatedTrainingClassValues {
+      get { return GetEstimatedClassValues(ProblemData.TrainingIndizes); }
+    }
+
+    public IEnumerable<double> EstimatedTestClassValues {
+      get { return GetEstimatedClassValues(ProblemData.TestIndizes); }
+    }
+
+    public IEnumerable<double> GetEstimatedClassValues(IEnumerable<int> rows) {
+      double[] classValues = ProblemData.SortedClassValues.ToArray();
+      foreach (int row in rows) {
+        double value = estimatedValues[row];
+        int classIndex = 0;
+        while (value > actualThresholds[classIndex + 1])
+          classIndex++;
+        yield return classValues[classIndex];
+      }
+    }
+    #endregion
+
+    public event EventHandler ThresholdsChanged;
+    private void OnThresholdsChanged() {
+      var handler = ThresholdsChanged;
+      if (handler != null)
+        ThresholdsChanged(this, EventArgs.Empty);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab/3.3/Files.txt
===================================================================
--- trunk/sources/HeuristicLab/3.3/Files.txt	(revision 4564)
+++ trunk/sources/HeuristicLab/3.3/Files.txt	(revision 4565)
@@ -46,4 +46,6 @@
 HeuristicLab.Problems.ArtificialAnt.Views\3.3:HeuristicLab.Problems.ArtificialAnt.Views-3.3.dll
 HeuristicLab.Problems.DataAnalysis\3.3:HeuristicLab.Problems.DataAnalysis-3.3.dll
+HeuristicLab.Problems.DataAnalysis.Classification\3.3:HeuristicLab.Problems.DataAnalysis.Classification-3.3.dll
+HeuristicLab.Problems.DataAnalysis.Classification.Views\3.3:HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll
 HeuristicLab.Problems.DataAnalysis.Regression\3.3:HeuristicLab.Problems.DataAnalysis.Regression-3.3.dll
 HeuristicLab.Problems.DataAnalysis.Views\3.3:HeuristicLab.Problems.DataAnalysis.Views-3.3.dll
