Index: branches/HeuristicLab.Classification/HeuristicLab.Classification.sln
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Classification.sln	(revision 4410)
+++ branches/HeuristicLab.Classification/HeuristicLab.Classification.sln	(revision 4417)
@@ -4,4 +4,5 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Classification", "HeuristicLab.Classification\HeuristicLab.Classification.csproj", "{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}"
 	ProjectSection(ProjectDependencies) = postProject
+		{7F038E9A-B91E-4F49-8C27-D47BC86F1220} = {7F038E9A-B91E-4F49-8C27-D47BC86F1220}
 		{D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E} = {D35FD6DB-D704-4BEA-BDAE-C40ABFB5B13E}
 	EndProjectSection
@@ -35,5 +36,6 @@
 		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|Any CPU.Build.0 = Release|Any CPU
-		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|x64.ActiveCfg = Release|Any CPU
+		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|x64.ActiveCfg = Release|x64
+		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|x64.Build.0 = Release|x64
 		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|x86.ActiveCfg = Release|x86
 		{3AB5A7E5-9F0C-4920-B18D-E06B9577618C}.Release|x86.Build.0 = Release|x86
@@ -46,5 +48,6 @@
 		{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|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
@@ -57,5 +60,6 @@
 		{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|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
Index: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.Designer.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.Designer.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.Designer.cs	(revision 4417)
@@ -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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/ConfusionMatrixView.cs	(revision 4417)
@@ -0,0 +1,150 @@
+﻿#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];
+        int start;
+        int end;
+
+        if (cmbSamples.SelectedItem.ToString() == TrainingSamples) {
+          start = Content.ProblemData.TrainingSamplesStart.Value;
+          end = Content.ProblemData.TrainingSamplesEnd.Value;
+        } else if (cmbSamples.SelectedItem.ToString() == TestSamples) {
+          start = Content.ProblemData.TestSamplesStart.Value;
+          end = Content.ProblemData.TestSamplesEnd.Value;
+        } 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.GetVariableValues(Content.ProblemData.TargetVariable.Value, start, end);
+        double[] predictedValues = Content.EstimatedClassValues.Skip(start).Take(end - start).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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.csproj	(revision 4417)
@@ -0,0 +1,186 @@
+﻿<?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="HeuristicLab.Common-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.Common-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Core-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.Core-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Data-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.Data-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.MainForm-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.MainForm.WindowsForms-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.MainForm.WindowsForms-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.Problems.DataAnalysis-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis.Regression-3.3">
+      <HintPath>c:\Program Files\HeuristicLab 3.3\HeuristicLab.Problems.DataAnalysis.Regression-3.3.dll</HintPath>
+    </Reference>
+    <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.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>
+  </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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs	(revision 4417)
@@ -0,0 +1,29 @@
+#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.0.0")]
+  [PluginFile("HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll", PluginFileType.Assembly)]
+  public class HeuristicLabProblemsDataAnalysisClassificationViewsPlugin : PluginBase {
+  }
+}
Index: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/HeuristicLabProblemsDataAnalysisClassificationViewsPlugin.cs.frame	(revision 4417)
@@ -0,0 +1,29 @@
+#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.0.$WCREV$")]
+  [PluginFile("HeuristicLab.Problems.DataAnalysis.Classification.Views-3.3.dll", PluginFileType.Assembly)]
+  public class HeuristicLabProblemsDataAnalysisClassificationViewsPlugin : PluginBase {
+  }
+}
Index: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/Properties/AssemblyInfo.frame
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/Properties/AssemblyInfo.frame	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/Properties/AssemblyInfo.frame	(revision 4417)
@@ -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.0.0")]
+[assembly: AssemblyFileVersion("3.3.0.$WCREV$")]
Index: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.Designer.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.Designer.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.Designer.cs	(revision 4417)
@@ -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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/RocCurvesView.cs	(revision 4417)
@@ -0,0 +1,262 @@
+﻿#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;
+        int samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
+        int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
+
+        if (cmbSamples.SelectedItem.ToString() == TrainingSamples) {
+          samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
+          samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
+        } else if (cmbSamples.SelectedItem.ToString() == TestSamples) {
+          samplesStart = Content.ProblemData.TestSamplesStart.Value;
+          samplesEnd = Content.ProblemData.TestSamplesEnd.Value;
+        } else throw new InvalidOperationException();
+
+        double[] estimatedValues = Content.EstimatedValues.Skip(samplesStart).Take(samplesEnd - samplesStart).ToArray();
+        double[] targetClassValues = Content.ProblemData.Dataset.GetVariableValues(Content.ProblemData.TargetVariable.Value)
+          .Skip(samplesStart).Take(samplesEnd - samplesStart).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 = samplesEnd - samplesStart - 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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.Designer.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.Designer.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.Designer.cs	(revision 4417)
@@ -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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification.Views/3.3/SymbolicClassificationSolutionView.cs	(revision 4417)
@@ -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) {
+      int row = Content.ProblemData.TrainingSamplesStart.Value;
+      foreach (double estimatedValue in Content.EstimatedTrainingValues) {
+        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 = 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);
+        }
+        row++;
+      }
+
+      row = Content.ProblemData.TestSamplesStart.Value;
+      foreach (double estimatedValue in Content.EstimatedTestValues) {
+        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);
+        }
+        row++;
+      }
+      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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj	(revision 4410)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/HeuristicLab.Problems.DataAnalysis.Classification-3.3.csproj	(revision 4417)
@@ -140,8 +140,5 @@
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
@@ -156,4 +153,5 @@
     <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" />
Index: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Analyzer/ValidationBestSymbolicClassificationSolutionAnalyzer.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Analyzer/ValidationBestSymbolicClassificationSolutionAnalyzer.cs	(revision 4410)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Analyzer/ValidationBestSymbolicClassificationSolutionAnalyzer.cs	(revision 4417)
@@ -55,8 +55,7 @@
     private const string BestValidationQualityParameterName = "Best validation quality";
     private const string BestValidationSolutionParameterName = "Best validation solution";
-    private const string BestSolutionGenerationParameterName = "Best solution generation";
-    private const string BestSolutionInputvariableCountParameterName = "Variables used by best solution";
+    private const string BestSolutionAccuracyTrainingParameterName = "Best solution accuracy (training)";
+    private const string BestSolutionAccuracyTestParameterName = "Best solution accuracy (test)";
     private const string VariableFrequenciesParameterName = "VariableFrequencies";
-    private const string VariableImpactsParameterName = "Variable Impacts";
 
     #region parameter properties
@@ -111,12 +110,9 @@
       get { return (ILookupParameter<SymbolicClassificationSolution>)Parameters[BestValidationSolutionParameterName]; }
     }
-    public ILookupParameter<IntValue> BestSolutionGenerationParameter {
-      get { return (ILookupParameter<IntValue>)Parameters[BestSolutionGenerationParameterName]; }
-    }
-    public ILookupParameter<DoubleMatrix> VariableImpactsParameter {
-      get { return (ILookupParameter<DoubleMatrix>)Parameters[VariableImpactsParameterName]; }
-    }
-    public ILookupParameter<IntValue> BestSolutionInputvariableCountParameter {
-      get { return (ILookupParameter<IntValue>)Parameters[BestSolutionInputvariableCountParameterName]; }
+    public ILookupParameter<DoubleValue> BestSolutionAccuracyTrainingParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[BestSolutionAccuracyTrainingParameterName]; }
+    }
+    public ILookupParameter<DoubleValue> BestSolutionAccuracyTestParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[BestSolutionAccuracyTestParameterName]; }
     }
     #endregion
@@ -174,15 +170,11 @@
       protected set { BestValidationSolutionParameter.ActualValue = value; }
     }
-    public IntValue BestSolutionGeneration {
-      get { return BestSolutionGenerationParameter.ActualValue; }
-      protected set { BestSolutionGenerationParameter.ActualValue = value; }
-    }
-    public IntValue BestSolutionInputvariableCount {
-      get { return BestSolutionInputvariableCountParameter.ActualValue; }
-      protected set { BestSolutionInputvariableCountParameter.ActualValue = value; }
-    }
-    public DoubleMatrix VariableImpacts {
-      get { return VariableImpactsParameter.ActualValue; }
-      protected set { VariableImpactsParameter.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
@@ -208,8 +200,6 @@
       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<IntValue>(BestSolutionGenerationParameterName, "The generation in which the best solution was found."));
-      Parameters.Add(new LookupParameter<DoubleMatrix>(VariableImpactsParameterName, "The impacts of the input variables calculated during the run."));
-      Parameters.Add(new LookupParameter<IntValue>(BestSolutionInputvariableCountParameterName, "The number of input variables used by the best solution."));
-
+      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."));
     }
 
@@ -272,45 +262,53 @@
           BestValidationSolution.Description = "Best solution on validation partition found over the whole run.";
           BestValidationQuality = new DoubleValue(bestQuality);
-          BestSolutionGeneration = (IntValue)Generations.Clone();
-          BestSolutionInputvariableCount = new IntValue(BestValidationSolution.Model.InputVariables.Count());
-
-          Results.Add(new Result(BestValidationSolutionParameterName, BestValidationSolution));
-          Results.Add(new Result(BestValidationQualityParameterName, BestValidationQuality));
-          Results.Add(new Result(BestSolutionGenerationParameterName, BestSolutionGeneration));
-
-          Results.Add(new Result(BestSolutionInputvariableCountParameterName, BestSolutionInputvariableCount));
-
-          if (VariableFrequencies != null) {
-            VariableImpacts = CalculateVariableImpacts(VariableFrequencies);
-            Results.Add(new Result(VariableImpactsParameterName, VariableImpacts));
-          }
-
         } else {
           BestValidationSolution.Model = model;
-          BestValidationQuality.Value = bestQuality;
-          BestSolutionGeneration.Value = Generations.Value;
-          BestSolutionInputvariableCount.Value = BestValidationSolution.Model.InputVariables.Count();
-
-          if (VariableFrequencies != null) {
-            VariableImpacts = CalculateVariableImpacts(VariableFrequencies);
-            Results[VariableImpactsParameterName].Value = VariableImpacts;
-          }
         }
+
+        UpdateBestSolutionResults();
       }
       return base.Apply();
     }
 
-    private static DoubleMatrix CalculateVariableImpacts(DataTable variableFrequencies) {
-      if (variableFrequencies != null) {
-        var impacts = new DoubleMatrix(variableFrequencies.Rows.Count, 1, new string[] { "Impact" }, variableFrequencies.Rows.Select(x => x.Name));
-        impacts.SortableView = true;
-        int rowIndex = 0;
-        foreach (var dataRow in variableFrequencies.Rows) {
-          string variableName = dataRow.Name;
-          impacts[rowIndex++, 0] = dataRow.Values.Average();
-        }
-        return impacts;
-      } else return new DoubleMatrix(1, 1);
-    }
+    private void UpdateBestSolutionResults() {
+      BestSymbolicRegressionSolutionAnalyzer.UpdateBestSolutionResults(BestValidationSolution, ClassificationProblemData, Results, Generations, VariableFrequencies);
+
+      IEnumerable<double> trainingValues = ClassificationProblemData.Dataset.GetEnumeratedVariableValues(
+        ClassificationProblemData.TargetVariable.Value,
+        ClassificationProblemData.TrainingSamplesStart.Value,
+        ClassificationProblemData.TrainingSamplesEnd.Value);
+      IEnumerable<double> testValues = ClassificationProblemData.Dataset.GetEnumeratedVariableValues(
+        ClassificationProblemData.TargetVariable.Value,
+        ClassificationProblemData.TestSamplesStart.Value,
+        ClassificationProblemData.TestSamplesEnd.Value);
+
+      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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/OnlineAccuracyEvaluator.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/OnlineAccuracyEvaluator.cs	(revision 4417)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/Evaluators/OnlineAccuracyEvaluator.cs	(revision 4417)
@@ -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: branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationSolution.cs
===================================================================
--- branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationSolution.cs	(revision 4410)
+++ branches/HeuristicLab.Classification/HeuristicLab.Problems.DataAnalysis.Classification/3.3/Symbolic/SymbolicClassificationSolution.cs	(revision 4417)
@@ -22,5 +22,4 @@
 using System;
 using System.Collections.Generic;
-using System.Drawing;
 using System.Linq;
 using HeuristicLab.Common;
@@ -35,18 +34,8 @@
   [Item("SymbolicClassificationSolution", "Represents a solution for a symbolic classification problem which can be visualized in the GUI.")]
   [StorableClass]
-  public class SymbolicClassificationSolution : DataAnalysisSolution, IClassificationSolution {
+  public class SymbolicClassificationSolution : SymbolicRegressionSolution, IClassificationSolution {
     private SymbolicClassificationSolution() : base() { }
     public SymbolicClassificationSolution(ClassificationProblemData problemData, SymbolicRegressionModel model, double lowerEstimationLimit, double upperEstimationLimit)
-      : base(problemData, lowerEstimationLimit, upperEstimationLimit) {
-      this.Model = model;
-    }
-
-    public override Image ItemImage {
-      get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Function; }
-    }
-
-    public new SymbolicRegressionModel Model {
-      get { return (SymbolicRegressionModel)base.Model; }
-      set { base.Model = value; }
+      : base(problemData, model, lowerEstimationLimit, upperEstimationLimit) {
     }
 
@@ -63,30 +52,4 @@
       RecalculateClassIntermediates();
       OnEstimatedValuesChanged();
-    }
-
-    protected List<double> estimatedValues;
-    public override IEnumerable<double> EstimatedValues {
-      get {
-        if (estimatedValues == null) RecalculateEstimatedValues();
-        return estimatedValues.AsEnumerable();
-      }
-    }
-
-    public override IEnumerable<double> EstimatedTrainingValues {
-      get {
-        if (estimatedValues == null) RecalculateEstimatedValues();
-        int start = ProblemData.TrainingSamplesStart.Value;
-        int n = ProblemData.TrainingSamplesEnd.Value - start;
-        return estimatedValues.Skip(start).Take(n).ToList();
-      }
-    }
-
-    public override IEnumerable<double> EstimatedTestValues {
-      get {
-        if (estimatedValues == null) RecalculateEstimatedValues();
-        int start = ProblemData.TestSamplesStart.Value;
-        int n = ProblemData.TestSamplesEnd.Value - start;
-        return estimatedValues.Skip(start).Take(n).ToList();
-      }
     }
 
