Index: /trunk/sources/HeuristicLab 3.3.sln
===================================================================
--- /trunk/sources/HeuristicLab 3.3.sln	(revision 3841)
+++ /trunk/sources/HeuristicLab 3.3.sln	(revision 3842)
@@ -32,4 +32,5 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab-3.3", "HeuristicLab\3.3\HeuristicLab-3.3.csproj", "{B1DCDECA-B56E-41D5-9850-EF0D3A77DEAF}"
 	ProjectSection(ProjectDependencies) = postProject
+		{89B50302-9CEE-4D13-9779-633EADCAE624} = {89B50302-9CEE-4D13-9779-633EADCAE624}
 		{125D3006-67F5-48CB-913E-73C0548F17FA} = {125D3006-67F5-48CB-913E-73C0548F17FA}
 		{489CFE09-FDF7-4C89-BAB5-BD09CADD61AD} = {489CFE09-FDF7-4C89-BAB5-BD09CADD61AD}
@@ -81,4 +82,5 @@
 		{DBECB8B0-B166-4133-BAF1-ED67C3FD7FCA} = {DBECB8B0-B166-4133-BAF1-ED67C3FD7FCA}
 		{887425B4-4348-49ED-A457-B7D2C26DDBF9} = {887425B4-4348-49ED-A457-B7D2C26DDBF9}
+		{A16F23B5-FB62-499E-A831-26953AA56FE2} = {A16F23B5-FB62-499E-A831-26953AA56FE2}
 		{F4539FB6-4708-40C9-BE64-0A1390AEA197} = {F4539FB6-4708-40C9-BE64-0A1390AEA197}
 		{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C} = {A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}
@@ -256,4 +258,12 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.ALGLIB-2.5.0", "HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\2.5.0\HeuristicLab.ALGLIB-2.5.0\HeuristicLab.ALGLIB-2.5.0.csproj", "{01BBCB5A-144A-4A7E-908E-079849E2F7CF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HeuristicLab.LibSVM", "HeuristicLab.LibSVM", "{782DDDA3-A7A3-404E-B751-6200CE2D5EF3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HeuristicLab.LibSVM-1.6.3", "HeuristicLab.LibSVM-1.6.3", "{16A50D44-107B-4601-A291-3B6870CD919D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibSVM-1.6.3", "HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\LibSVM-1.6.3\LibSVM-1.6.3.csproj", "{A16F23B5-FB62-499E-A831-26953AA56FE2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.LibSVM-1.6.3", "HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\HeuristicLab.LibSVM-1.6.3\HeuristicLab.LibSVM-1.6.3.csproj", "{89B50302-9CEE-4D13-9779-633EADCAE624}"
 EndProject
 Global
@@ -1412,4 +1422,34 @@
 		{01BBCB5A-144A-4A7E-908E-079849E2F7CF}.Services|x64.ActiveCfg = Release|Any CPU
 		{01BBCB5A-144A-4A7E-908E-079849E2F7CF}.Services|x86.ActiveCfg = Release|Any CPU
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Debug|x64.ActiveCfg = Debug|x64
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Debug|x64.Build.0 = Debug|x64
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Debug|x86.ActiveCfg = Debug|x86
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Debug|x86.Build.0 = Debug|x86
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Release|x64.ActiveCfg = Release|x64
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Release|x64.Build.0 = Release|x64
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Release|x86.ActiveCfg = Release|x86
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Release|x86.Build.0 = Release|x86
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Services|Any CPU.ActiveCfg = Release|Any CPU
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Services|x64.ActiveCfg = Release|x64
+		{A16F23B5-FB62-499E-A831-26953AA56FE2}.Services|x86.ActiveCfg = Release|x86
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Debug|x64.ActiveCfg = Debug|x64
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Debug|x64.Build.0 = Debug|x64
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Debug|x86.ActiveCfg = Debug|x86
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Debug|x86.Build.0 = Debug|x86
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Release|Any CPU.Build.0 = Release|Any CPU
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Release|x64.ActiveCfg = Release|x64
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Release|x64.Build.0 = Release|x64
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Release|x86.ActiveCfg = Release|x86
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Release|x86.Build.0 = Release|x86
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Services|Any CPU.ActiveCfg = Release|Any CPU
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Services|x64.ActiveCfg = Release|x64
+		{89B50302-9CEE-4D13-9779-633EADCAE624}.Services|x86.ActiveCfg = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
@@ -1422,4 +1462,5 @@
 		{F94E41E4-F25F-4302-8486-0BEF121CF5C8} = {07BCBC57-3E15-4582-B306-C046E516C49C}
 		{F0D06B07-1CB3-418E-88ED-CAE8DAACC7E0} = {07BCBC57-3E15-4582-B306-C046E516C49C}
+		{782DDDA3-A7A3-404E-B751-6200CE2D5EF3} = {07BCBC57-3E15-4582-B306-C046E516C49C}
 		{99AD3658-DB36-4E26-B4CC-6FEAACC5C88C} = {7F485A48-A80F-4454-9A9B-7B126B43861C}
 		{678E2145-8152-4E19-9646-07D439D00301} = {99AD3658-DB36-4E26-B4CC-6FEAACC5C88C}
@@ -1433,4 +1474,7 @@
 		{29E4B033-1FEF-4FE1-AE17-0A9319D7C54E} = {F1A195C9-98CD-47C6-9B74-3344EB258C5D}
 		{01BBCB5A-144A-4A7E-908E-079849E2F7CF} = {F1A195C9-98CD-47C6-9B74-3344EB258C5D}
+		{16A50D44-107B-4601-A291-3B6870CD919D} = {782DDDA3-A7A3-404E-B751-6200CE2D5EF3}
+		{A16F23B5-FB62-499E-A831-26953AA56FE2} = {16A50D44-107B-4601-A291-3B6870CD919D}
+		{89B50302-9CEE-4D13-9779-633EADCAE624} = {16A50D44-107B-4601-A291-3B6870CD919D}
 	EndGlobalSection
 EndGlobal
Index: unk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/2.5.0/HeuristicLab.ALGLIB-2.5.0/HeuristicLabALGLIBPlugin.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/2.5.0/HeuristicLab.ALGLIB-2.5.0/HeuristicLabALGLIBPlugin.cs	(revision 3841)
+++ 	(revision )
@@ -1,35 +1,0 @@
-﻿#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.Text;
-using HeuristicLab.PluginInfrastructure;
-
-namespace HeuristicLab.ALGLIB {
-  [Plugin("HeuristicLab.ALGLIB","2.5.0.0")]  
-  [PluginFile("HeuristicLab.ALGLIB-2.5.0.dll", PluginFileType.Assembly)]
-  [PluginFile("ALGLIB-2.5.0.dll", PluginFileType.Assembly)]
-  [PluginFile("ALGLIB License-2.5.0.txt", PluginFileType.License)]
-  public class HeuristicLabAlgLibPlugin : PluginBase {
-  }
-}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLab.LibSVM-1.6.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLab.LibSVM-1.6.3.csproj	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLab.LibSVM-1.6.3.csproj	(revision 3842)
@@ -0,0 +1,125 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{89B50302-9CEE-4D13-9779-633EADCAE624}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.LibSVM</RootNamespace>
+    <AssemblyName>HeuristicLab.LibSVM-1.6.3</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>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>
+    <DocumentationFile>bin\Release\HeuristicLab.LibSVM-1.6.3.XML</DocumentationFile>
+  </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>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>bin\Release\HeuristicLab.LibSVM-1.6.3.XML</DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </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>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>bin\Release\HeuristicLab.LibSVM-1.6.3.XML</DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLabLibSVMPlugin.cs.frame" />
+    <Compile Include="HeuristicLabLibSVMPlugin.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="SVM.NET-1.6.3 License.txt">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+    <None Include="Properties\AssemblyInfo.frame" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\LibSVM-1.6.3\LibSVM-1.6.3.csproj">
+      <Project>{A16F23B5-FB62-499E-A831-26953AA56FE2}</Project>
+      <Name>LibSVM-1.6.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent>set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+SubWCRev "%25ProjectDir%25\" "%25ProjectDir%25\HeuristicLabLibSVMPlugin.cs.frame" "%25ProjectDir%25\HeuristicLabLibSVMPlugin.cs"</PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLabLibSVMPlugin.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLabLibSVMPlugin.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLabLibSVMPlugin.cs	(revision 3842)
@@ -0,0 +1,35 @@
+﻿#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.Text;
+
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.LibSVM {
+  [Plugin("HeuristicLab.LibSVM", "1.6.3.2645")]
+  [PluginFile("HeuristicLab.LibSVM-1.6.3.dll", PluginFileType.Assembly)]
+  [PluginFile("LibSVM-1.6.3.dll", PluginFileType.Assembly)]
+  [PluginFile("SVM.NET-1.6.3 License.txt",PluginFileType.License)]
+  public class HeuristicLabLibSVMPlugin : PluginBase {
+  }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLabLibSVMPlugin.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLabLibSVMPlugin.cs.frame	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/HeuristicLabLibSVMPlugin.cs.frame	(revision 3842)
@@ -0,0 +1,35 @@
+﻿#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.Text;
+
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.LibSVM {
+  [Plugin("HeuristicLab.LibSVM", "1.6.3.$WCREV$")]
+  [PluginFile("HeuristicLab.LibSVM-1.6.3.dll", PluginFileType.Assembly)]
+  [PluginFile("LibSVM-1.6.3.dll", PluginFileType.Assembly)]
+  [PluginFile("SVM.NET-1.6.3 License.txt",PluginFileType.License)]
+  public class HeuristicLabLibSVMPlugin : PluginBase {
+  }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/LibSVM license.txt
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/LibSVM license.txt	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/LibSVM license.txt	(revision 3842)
@@ -0,0 +1,280 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/Properties/AssemblyInfo.frame
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/Properties/AssemblyInfo.frame	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/Properties/AssemblyInfo.frame	(revision 3842)
@@ -0,0 +1,56 @@
+﻿#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.CompilerServices;
+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.LibSVM")]
+[assembly: AssemblyDescription("HeuristicLab transport plugin for SVM.NET by Matthew Johnson which is a C# port of libSVM by Chih-Chung Chang and Chih-Jen Lin")]
+[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("3f5083f8-2738-4573-b230-e9928ef61e6b")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.6.3.0")]
+[assembly: AssemblyFileVersion("1.6.3.$WCREV$")]
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/SVM.NET-1.6.3 License.txt
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/SVM.NET-1.6.3 License.txt	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/HeuristicLab.LibSVM-1.6.3/SVM.NET-1.6.3 License.txt	(revision 3842)
@@ -0,0 +1,16 @@
+
+SVM.NET Library
+Copyright (C) 2009 Matthew Johnson
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Cache.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Cache.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Cache.cs	(revision 3842)
@@ -0,0 +1,161 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+
+namespace SVM
+{
+    internal class Cache
+    {
+        private int _count;
+        private long _size;
+
+        private sealed class head_t
+        {
+            public head_t(Cache enclosingInstance)
+            {
+                _enclosingInstance = enclosingInstance;
+            }
+            private Cache _enclosingInstance;
+            public Cache EnclosingInstance
+            {
+                get
+                {
+                    return _enclosingInstance;
+                }
+            }
+            internal head_t prev, next; // a cicular list
+            internal float[] data;
+            internal int len; // data[0,len) is cached in this entry
+        }
+
+        private head_t[] head;
+        private head_t lru_head;
+
+        public Cache(int count, long size)
+        {
+            _count = count;
+            _size = size;
+            head = new head_t[_count];
+            for (int i = 0; i < _count; i++)
+                head[i] = new head_t(this);
+            _size /= 4;
+            _size -= _count * (16 / 4); // sizeof(head_t) == 16
+            lru_head = new head_t(this);
+            lru_head.next = lru_head.prev = lru_head;
+        }
+
+        private void lru_delete(head_t h)
+        {
+            // delete from current location
+            h.prev.next = h.next;
+            h.next.prev = h.prev;
+        }
+
+        private void lru_insert(head_t h)
+        {
+            // insert to last position
+            h.next = lru_head;
+            h.prev = lru_head.prev;
+            h.prev.next = h;
+            h.next.prev = h;
+        }
+
+        private static void swap<T>(ref T lhs, ref T rhs)
+        {
+            T tmp = lhs;
+            lhs = rhs;
+            rhs = tmp;
+        }
+
+        // request data [0,len)
+        // return some position p where [p,len) need to be filled
+        // (p >= len if nothing needs to be filled)
+        // java: simulate pointer using single-element array
+        public int GetData(int index, ref float[] data, int len)
+        {
+            head_t h = head[index];
+            if (h.len > 0)
+                lru_delete(h);
+            int more = len - h.len;
+
+            if (more > 0)
+            {
+                // free old space
+                while (_size < more)
+                {
+                    head_t old = lru_head.next;
+                    lru_delete(old);
+                    _size += old.len;
+                    old.data = null;
+                    old.len = 0;
+                }
+
+                // allocate new space
+                float[] new_data = new float[len];
+                if (h.data != null)
+                    Array.Copy(h.data, 0, new_data, 0, h.len);
+                h.data = new_data;
+                _size -= more;
+                swap(ref h.len, ref len);
+            }
+
+            lru_insert(h);
+            data = h.data;
+            return len;
+        }
+
+        public void SwapIndex(int i, int j)
+        {
+            if (i == j)
+                return;
+
+            if (head[i].len > 0)
+                lru_delete(head[i]);
+            if (head[j].len > 0)
+                lru_delete(head[j]);
+            swap(ref head[i].data, ref head[j].data);
+            swap(ref head[i].len, ref head[j].len);
+            if (head[i].len > 0)
+                lru_insert(head[i]);
+            if (head[j].len > 0)
+                lru_insert(head[j]);
+
+            if (i > j)
+                swap(ref i, ref j);
+
+            for (head_t h = lru_head.next; h != lru_head; h = h.next)
+            {
+                if (h.len > i)
+                {
+                    if (h.len > j)
+                        swap(ref h.data[i], ref h.data[j]);
+                    else
+                    {
+                        // give up
+                        lru_delete(h);
+                        _size += h.len;
+                        h.data = null;
+                        h.len = 0;
+                    }
+                }
+            }
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/GaussianTransform.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/GaussianTransform.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/GaussianTransform.cs	(revision 3842)
@@ -0,0 +1,209 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Globalization;
+using System.Threading;
+
+namespace SVM
+{
+    /// <summary>
+    /// A transform which learns the mean and variance of a sample set and uses these to transform new data
+    /// so that it has zero mean and unit variance.
+    /// </summary>
+    public class GaussianTransform : IRangeTransform
+    {
+        private double[] _means;
+        private double[] _stddevs;
+
+        /// <summary>
+        /// Determines the Gaussian transform for the provided problem.
+        /// </summary>
+        /// <param name="prob">The Problem to analyze</param>
+        /// <returns>The Gaussian transform for the problem</returns>
+        public static GaussianTransform Compute(Problem prob)
+        {
+            int[] counts = new int[prob.MaxIndex];
+            double[] means = new double[prob.MaxIndex];
+            foreach (Node[] sample in prob.X)
+            {
+                for (int i = 0; i < sample.Length; i++)
+                {
+                    means[sample[i].Index-1] += sample[i].Value;
+                    counts[sample[i].Index-1]++;
+                }
+            }
+            for (int i = 0; i < prob.MaxIndex; i++)
+            {
+                if (counts[i] == 0)
+                    counts[i] = 2;
+                means[i] /= counts[i];
+            }
+
+            double[] stddevs = new double[prob.MaxIndex];
+            foreach (Node[] sample in prob.X)
+            {
+                for (int i = 0; i < sample.Length; i++)
+                {
+                    double diff = sample[i].Value - means[sample[i].Index - 1];
+                    stddevs[sample[i].Index - 1] += diff * diff;
+                }
+            }
+            for (int i = 0; i < prob.MaxIndex; i++)
+            {
+                if (stddevs[i] == 0)
+                    continue;
+                stddevs[i] /= (counts[i] - 1);
+                stddevs[i] = Math.Sqrt(stddevs[i]);
+            }
+
+            return new GaussianTransform(means, stddevs);
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="means">Means in each dimension</param>
+        /// <param name="stddevs">Standard deviation in each dimension</param>
+        public GaussianTransform(double[] means, double[] stddevs)
+        {
+            _means = means;
+            _stddevs = stddevs;
+        }
+
+        /// <summary>
+        /// Saves the transform to the disk.  The samples are not stored, only the 
+        /// statistics.
+        /// </summary>
+        /// <param name="stream">The destination stream</param>
+        /// <param name="transform">The transform</param>
+        public static void Write(Stream stream, GaussianTransform transform)
+        {
+            TemporaryCulture.Start();
+
+            StreamWriter output = new StreamWriter(stream);
+            output.WriteLine(transform._means.Length);
+            for (int i = 0; i < transform._means.Length; i++)
+                output.WriteLine("{0} {1}", transform._means[i], transform._stddevs[i]);
+            output.Flush();
+
+            TemporaryCulture.Stop();
+        }
+
+        /// <summary>
+        /// Reads a GaussianTransform from the provided stream.
+        /// </summary>
+        /// <param name="stream">The source stream</param>
+        /// <returns>The transform</returns>
+        public static GaussianTransform Read(Stream stream)
+        {
+            TemporaryCulture.Start();
+
+            StreamReader input = new StreamReader(stream);
+            int length = int.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
+            double[] means = new double[length];
+            double[] stddevs = new double[length];
+            for (int i = 0; i < length; i++)
+            {
+                string[] parts = input.ReadLine().Split();
+                means[i] = double.Parse(parts[0], CultureInfo.InvariantCulture);
+                stddevs[i] = double.Parse(parts[1], CultureInfo.InvariantCulture);
+            }
+
+            TemporaryCulture.Stop();
+
+            return new GaussianTransform(means, stddevs);
+        }
+
+        /// <summary>
+        /// Saves the transform to the disk.  The samples are not stored, only the 
+        /// statistics.
+        /// </summary>
+        /// <param name="filename">The destination filename</param>
+        /// <param name="transform">The transform</param>
+        public static void Write(string filename, GaussianTransform transform)
+        {
+            FileStream output = File.Open(filename, FileMode.Create);
+            try
+            {
+                Write(output, transform);
+            }
+            finally
+            {
+                output.Close();
+            }
+        }
+
+        /// <summary>
+        /// Reads a GaussianTransform from the provided stream.
+        /// </summary>
+        /// <param name="filename">The source filename</param>
+        /// <returns>The transform</returns>
+        public static GaussianTransform Read(string filename)
+        {
+            FileStream input = File.Open(filename, FileMode.Open);
+            try
+            {
+                return Read(input);
+            }
+            finally
+            {
+                input.Close();
+            }
+        }
+
+        #region IRangeTransform Members
+
+        /// <summary>
+        /// Transform the input value using the transform stored for the provided index.
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <param name="index">Index of the transform to use</param>
+        /// <returns>The transformed value</returns>
+        public double Transform(double input, int index)
+        {
+            index--;
+            if (_stddevs[index] == 0)
+                return 0;
+            double diff = input - _means[index];
+            diff /= _stddevs[index];
+            return diff;
+        }
+        /// <summary>
+        /// Transforms the input array.
+        /// </summary>
+        /// <param name="input">The array to transform</param>
+        /// <returns>The transformed array</returns>
+        public Node[] Transform(Node[] input)
+        {
+            Node[] output = new Node[input.Length];
+            for (int i = 0; i < output.Length; i++)
+            {
+                int index = input[i].Index;
+                double value = input[i].Value;
+                output[i] = new Node(index, Transform(value, index));
+            }
+            return output;
+        }
+
+        #endregion
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/IRangeTransform.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/IRangeTransform.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/IRangeTransform.cs	(revision 3842)
@@ -0,0 +1,41 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+namespace SVM
+{
+    /// <summary>
+    /// Interface implemented by range transforms.
+    /// </summary>
+    public interface IRangeTransform
+    {
+        /// <summary>
+        /// Transform the input value using the transform stored for the provided index.
+        /// </summary>
+        /// <param name="input">Input value</param>
+        /// <param name="index">Index of the transform to use</param>
+        /// <returns>The transformed value</returns>
+        double Transform(double input, int index);
+        /// <summary>
+        /// Transforms the input array.
+        /// </summary>
+        /// <param name="input">The array to transform</param>
+        /// <returns>The transformed array</returns>
+        Node[] Transform(Node[] input);
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Kernel.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Kernel.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Kernel.cs	(revision 3842)
@@ -0,0 +1,226 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SVM
+{
+    internal interface IQMatrix
+    {
+        float[] GetQ(int column, int len);
+        float[] GetQD();
+        void SwapIndex(int i, int j);
+    }
+
+    internal abstract class Kernel : IQMatrix
+    {
+        private Node[][] _x;
+        private double[] _xSquare;
+
+        private KernelType _kernelType;
+        private int _degree;
+        private double _gamma;
+        private double _coef0;
+
+        public abstract float[] GetQ(int column, int len);
+        public abstract float[] GetQD();
+
+        public virtual void SwapIndex(int i, int j)
+        {
+            _x.SwapIndex(i, j);
+
+            if (_xSquare != null)
+            {
+                _xSquare.SwapIndex(i, j);
+            }
+        }
+
+        private static double powi(double value, int times)
+        {
+            double tmp = value, ret = 1.0;
+
+            for (int t = times; t > 0; t /= 2)
+            {
+                if (t % 2 == 1) ret *= tmp;
+                tmp = tmp * tmp;
+            }
+            return ret;
+        }
+
+        public double KernelFunction(int i, int j)
+        {
+            switch (_kernelType)
+            {
+                case KernelType.LINEAR:
+                    return dot(_x[i], _x[j]);
+                case KernelType.POLY:
+                    return powi(_gamma * dot(_x[i], _x[j]) + _coef0, _degree);
+                case KernelType.RBF:
+                    return Math.Exp(-_gamma * (_xSquare[i] + _xSquare[j] - 2 * dot(_x[i], _x[j])));
+                case KernelType.SIGMOID:
+                    return Math.Tanh(_gamma * dot(_x[i], _x[j]) + _coef0);
+                case KernelType.PRECOMPUTED:
+                    return _x[i][(int)(_x[j][0].Value)].Value;
+                default:
+                    return 0;
+            }
+        }
+
+        public Kernel(int l, Node[][] x_, Parameter param)
+        {
+            _kernelType = param.KernelType;
+            _degree = param.Degree;
+            _gamma = param.Gamma;
+            _coef0 = param.Coefficient0;
+
+            _x = (Node[][])x_.Clone();
+
+            if (_kernelType == KernelType.RBF)
+            {
+                _xSquare = new double[l];
+                for (int i = 0; i < l; i++)
+                    _xSquare[i] = dot(_x[i], _x[i]);
+            }
+            else _xSquare = null;
+        }
+
+        private static double dot(Node[] xNodes, Node[] yNodes)
+        {
+            double sum = 0;
+            int xlen = xNodes.Length;
+            int ylen = yNodes.Length;
+            int i = 0;
+            int j = 0;
+            Node x = xNodes[0];
+            Node y = yNodes[0];
+            while (true)
+            {
+                if (x._index == y._index)
+                {
+                    sum += x._value * y._value;
+                    i++;
+                    j++;
+                    if (i < xlen && j < ylen)
+                    {
+                        x = xNodes[i];
+                        y = yNodes[j];
+                    }
+                    else if (i < xlen)
+                    {
+                        x = xNodes[i];
+                        break;
+                    }
+                    else if (j < ylen)
+                    {
+                        y = yNodes[j];
+                        break;
+                    }
+                    else break;
+                }
+                else
+                {
+                    if (x._index > y._index)
+                    {
+                        ++j;
+                        if (j < ylen)
+                            y = yNodes[j];
+                        else break;
+                    }
+                    else
+                    {
+                        ++i;
+                        if (i < xlen)
+                            x = xNodes[i];
+                        else break;
+                    }
+                }
+            }
+            return sum;
+        }
+
+        private static double computeSquaredDistance(Node[] xNodes, Node[] yNodes)
+        {
+            Node x = xNodes[0];
+            Node y = yNodes[0];
+            int xLength = xNodes.Length;
+            int yLength = yNodes.Length;
+            int xIndex = 0;
+            int yIndex = 0;
+            double sum = 0;
+
+            while (true)
+            {
+                if (x._index == y._index)
+                {
+                    double d = x._value - y._value;
+                    sum += d * d;
+                    xIndex++;
+                    yIndex++;
+                    if (xIndex < xLength && yIndex < yLength)
+                    {
+                        x = xNodes[xIndex];
+                        y = yNodes[yIndex];
+                    }
+                    else if(xIndex < xLength){
+                        x = xNodes[xIndex];
+                        break;
+                    }
+                    else if(yIndex < yLength){
+                        y = yNodes[yIndex];
+                        break;
+                    }else break;
+                }
+                else if (x._index > y._index)
+                {
+                    sum += y._value * y._value;
+                    if (++yIndex < yLength)
+                        y = yNodes[yIndex];
+                    else break;
+                }
+                else
+                {
+                    sum += x._value * x._value;
+                    if (++xIndex < xLength)
+                        x = xNodes[xIndex];
+                    else break;
+                }
+            }
+
+            for (; xIndex < xLength; xIndex++)
+            {
+                double d = xNodes[xIndex]._value;
+                sum += d * d;
+            }
+
+            for (; yIndex < yLength; yIndex++)
+            {
+                double d = yNodes[yIndex]._value;
+                sum += d * d;
+            }
+
+            return sum;
+        }
+
+        public static double KernelFunction(Node[] x, Node[] y, Parameter param)
+        {
+            switch (param.KernelType)
+            {
+                case KernelType.LINEAR:
+                    return dot(x, y);
+                case KernelType.POLY:
+                    return powi(param.Degree * dot(x, y) + param.Coefficient0, param.Degree);
+                case KernelType.RBF:
+                    {
+                        double sum = computeSquaredDistance(x, y);
+                        return Math.Exp(-param.Gamma * sum);
+                    }
+                case KernelType.SIGMOID:
+                    return Math.Tanh(param.Gamma * dot(x, y) + param.Coefficient0);
+                case KernelType.PRECOMPUTED:
+                    return x[(int)(y[0].Value)].Value;
+                default:
+                    return 0;
+            }
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/LibSVM-1.6.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/LibSVM-1.6.3.csproj	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/LibSVM-1.6.3.csproj	(revision 3842)
@@ -0,0 +1,118 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A16F23B5-FB62-499E-A831-26953AA56FE2}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SVM</RootNamespace>
+    <AssemblyName>LibSVM-1.6.3</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>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 Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <DocumentationFile>bin\x64\Release\LibSVM-1.6.3.xml</DocumentationFile>
+  </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>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Kernel.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Cache.cs" />
+    <Compile Include="GaussianTransform.cs" />
+    <Compile Include="IRangeTransform.cs" />
+    <Compile Include="Model.cs" />
+    <Compile Include="Node.cs" />
+    <Compile Include="Parameter.cs" />
+    <Compile Include="ParameterSelection.cs" />
+    <Compile Include="PerformanceEvaluator.cs" />
+    <Compile Include="PrecomputedKernel.cs" />
+    <Compile Include="Prediction.cs" />
+    <Compile Include="Problem.cs" />
+    <Compile Include="RangeTransform.cs" />
+    <Compile Include="Scaling.cs" />
+    <Compile Include="Solver.cs" />
+    <Compile Include="SVMExtensions.cs" />
+    <Compile Include="TemporaryCulture.cs" />
+    <Compile Include="Training.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+  </PropertyGroup>
+</Project>
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Model.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Model.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Model.cs	(revision 3842)
@@ -0,0 +1,438 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Globalization;
+
+namespace SVM {
+  /// <summary>
+  /// Encapsulates an SVM Model.
+  /// </summary>
+  [Serializable]
+  public class Model {
+    private Parameter _parameter;
+    private int _numberOfClasses;
+    private int _supportVectorCount;
+    private Node[][] _supportVectors;
+    private double[][] _supportVectorCoefficients;
+    private double[] _rho;
+    private double[] _pairwiseProbabilityA;
+    private double[] _pairwiseProbabilityB;
+
+    private int[] _classLabels;
+    private int[] _numberOfSVPerClass;
+
+    internal Model() {
+    }
+
+    /// <summary>
+    /// Parameter object.
+    /// </summary>
+    public Parameter Parameter {
+      get {
+        return _parameter;
+      }
+      set {
+        _parameter = value;
+      }
+    }
+
+    /// <summary>
+    /// Number of classes in the model.
+    /// </summary>
+    public int NumberOfClasses {
+      get {
+        return _numberOfClasses;
+      }
+      set {
+        _numberOfClasses = value;
+      }
+    }
+
+    /// <summary>
+    /// Total number of support vectors.
+    /// </summary>
+    public int SupportVectorCount {
+      get {
+        return _supportVectorCount;
+      }
+      set {
+        _supportVectorCount = value;
+      }
+    }
+
+    /// <summary>
+    /// The support vectors.
+    /// </summary>
+    public Node[][] SupportVectors {
+      get {
+        return _supportVectors;
+      }
+      set {
+        _supportVectors = value;
+      }
+    }
+
+    /// <summary>
+    /// The coefficients for the support vectors.
+    /// </summary>
+    public double[][] SupportVectorCoefficients {
+      get {
+        return _supportVectorCoefficients;
+      }
+      set {
+        _supportVectorCoefficients = value;
+      }
+    }
+
+    /// <summary>
+    /// Rho values.
+    /// </summary>
+    public double[] Rho {
+      get {
+        return _rho;
+      }
+      set {
+        _rho = value;
+      }
+    }
+
+    /// <summary>
+    /// First pairwise probability.
+    /// </summary>
+    public double[] PairwiseProbabilityA {
+      get {
+        return _pairwiseProbabilityA;
+      }
+      set {
+        _pairwiseProbabilityA = value;
+      }
+    }
+
+    /// <summary>
+    /// Second pairwise probability.
+    /// </summary>
+    public double[] PairwiseProbabilityB {
+      get {
+        return _pairwiseProbabilityB;
+      }
+      set {
+        _pairwiseProbabilityB = value;
+      }
+    }
+
+    // for classification only
+
+    /// <summary>
+    /// Class labels.
+    /// </summary>
+    public int[] ClassLabels {
+      get {
+        return _classLabels;
+      }
+      set {
+        _classLabels = value;
+      }
+    }
+
+    /// <summary>
+    /// Number of support vectors per class.
+    /// </summary>
+    public int[] NumberOfSVPerClass {
+      get {
+        return _numberOfSVPerClass;
+      }
+      set {
+        _numberOfSVPerClass = value;
+      }
+    }
+
+    /// <summary>
+    /// Reads a Model from the provided file.
+    /// </summary>
+    /// <param name="filename">The name of the file containing the Model</param>
+    /// <returns>the Model</returns>
+    public static Model Read(string filename) {
+      FileStream input = File.OpenRead(filename);
+      try {
+        return Read(input);
+      }
+      finally {
+        input.Close();
+      }
+    }
+
+    public static Model Read(Stream stream) {
+      return Read(new StreamReader(stream));
+    }
+
+    /// <summary>
+    /// Reads a Model from the provided stream.
+    /// </summary>
+    /// <param name="stream">The stream from which to read the Model.</param>
+    /// <returns>the Model</returns>
+    public static Model Read(TextReader input) {
+      TemporaryCulture.Start();
+
+      // read parameters
+
+      Model model = new Model();
+      Parameter param = new Parameter();
+      model.Parameter = param;
+      model.Rho = null;
+      model.PairwiseProbabilityA = null;
+      model.PairwiseProbabilityB = null;
+      model.ClassLabels = null;
+      model.NumberOfSVPerClass = null;
+
+      bool headerFinished = false;
+      while (!headerFinished) {
+        string line = input.ReadLine();
+        string cmd, arg;
+        int splitIndex = line.IndexOf(' ');
+        if (splitIndex >= 0) {
+          cmd = line.Substring(0, splitIndex);
+          arg = line.Substring(splitIndex + 1);
+        } else {
+          cmd = line;
+          arg = "";
+        }
+        // arg = arg.ToLower(); (transforms double NaN or Infinity values to incorrect format [gkronber])
+
+        int i, n;
+        switch (cmd) {
+          case "svm_type":
+            param.SvmType = (SvmType)Enum.Parse(typeof(SvmType), arg.ToUpper());
+            break;
+
+          case "kernel_type":
+            param.KernelType = (KernelType)Enum.Parse(typeof(KernelType), arg.ToUpper());
+            break;
+
+          case "degree":
+            param.Degree = int.Parse(arg);
+            break;
+
+          case "gamma":
+            param.Gamma = double.Parse(arg);
+            break;
+
+          case "coef0":
+            param.Coefficient0 = double.Parse(arg);
+            break;
+
+          case "nr_class":
+            model.NumberOfClasses = int.Parse(arg);
+            break;
+
+          case "total_sv":
+            model.SupportVectorCount = int.Parse(arg);
+            break;
+
+          case "rho":
+            n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
+            model.Rho = new double[n];
+            string[] rhoParts = arg.Split();
+            for (i = 0; i < n; i++)
+              model.Rho[i] = double.Parse(rhoParts[i]);
+            break;
+
+          case "label":
+            n = model.NumberOfClasses;
+            model.ClassLabels = new int[n];
+            string[] labelParts = arg.Split();
+            for (i = 0; i < n; i++)
+              model.ClassLabels[i] = int.Parse(labelParts[i]);
+            break;
+
+          case "probA":
+            n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
+            model.PairwiseProbabilityA = new double[n];
+            string[] probAParts = arg.Split();
+            for (i = 0; i < n; i++)
+              model.PairwiseProbabilityA[i] = double.Parse(probAParts[i]);
+            break;
+
+          case "probB":
+            n = model.NumberOfClasses * (model.NumberOfClasses - 1) / 2;
+            model.PairwiseProbabilityB = new double[n];
+            string[] probBParts = arg.Split();
+            for (i = 0; i < n; i++)
+              model.PairwiseProbabilityB[i] = double.Parse(probBParts[i]);
+            break;
+
+          case "nr_sv":
+            n = model.NumberOfClasses;
+            model.NumberOfSVPerClass = new int[n];
+            string[] nrsvParts = arg.Split();
+            for (i = 0; i < n; i++)
+              model.NumberOfSVPerClass[i] = int.Parse(nrsvParts[i]);
+            break;
+
+          case "SV":
+            headerFinished = true;
+            break;
+
+          default:
+            throw new Exception("Unknown text in model file");
+        }
+      }
+
+      // read sv_coef and SV
+
+      int m = model.NumberOfClasses - 1;
+      int l = model.SupportVectorCount;
+      model.SupportVectorCoefficients = new double[m][];
+      for (int i = 0; i < m; i++) {
+        model.SupportVectorCoefficients[i] = new double[l];
+      }
+      model.SupportVectors = new Node[l][];
+
+      for (int i = 0; i < l; i++) {
+        string[] parts = input.ReadLine().Trim().Split();
+
+        for (int k = 0; k < m; k++)
+          model.SupportVectorCoefficients[k][i] = double.Parse(parts[k]);
+        int n = parts.Length - m;
+        model.SupportVectors[i] = new Node[n];
+        for (int j = 0; j < n; j++) {
+          string[] nodeParts = parts[m + j].Split(':');
+          model.SupportVectors[i][j] = new Node();
+          model.SupportVectors[i][j].Index = int.Parse(nodeParts[0]);
+          model.SupportVectors[i][j].Value = double.Parse(nodeParts[1]);
+        }
+      }
+
+      TemporaryCulture.Stop();
+
+      return model;
+    }
+
+    /// <summary>
+    /// Writes a model to the provided filename.  This will overwrite any previous data in the file.
+    /// </summary>
+    /// <param name="filename">The desired file</param>
+    /// <param name="model">The Model to write</param>
+    public static void Write(string filename, Model model) {
+      FileStream stream = File.Open(filename, FileMode.Create);
+      try {
+        Write(stream, model);
+      }
+      finally {
+        stream.Close();
+      }
+    }
+
+    /// <summary>
+    /// Writes a model to the provided stream.
+    /// </summary>
+    /// <param name="stream">The output stream</param>
+    /// <param name="model">The model to write</param>
+    public static void Write(Stream stream, Model model) {
+      TemporaryCulture.Start();
+
+      StreamWriter output = new StreamWriter(stream);
+
+      Parameter param = model.Parameter;
+
+      output.Write("svm_type " + param.SvmType + Environment.NewLine);
+      output.Write("kernel_type " + param.KernelType + Environment.NewLine);
+
+      if (param.KernelType == KernelType.POLY)
+        output.Write("degree " + param.Degree.ToString("r") + Environment.NewLine);
+
+      if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.RBF || param.KernelType == KernelType.SIGMOID)
+        output.Write("gamma " + param.Gamma.ToString("r") + Environment.NewLine);
+
+      if (param.KernelType == KernelType.POLY || param.KernelType == KernelType.SIGMOID)
+        output.Write("coef0 " + param.Coefficient0.ToString("r") + Environment.NewLine);
+
+      int nr_class = model.NumberOfClasses;
+      int l = model.SupportVectorCount;
+      output.Write("nr_class " + nr_class + Environment.NewLine);
+      output.Write("total_sv " + l + Environment.NewLine);
+
+      {
+        output.Write("rho");
+        for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
+          output.Write(" " + model.Rho[i].ToString("r"));
+        output.Write(Environment.NewLine);
+      }
+
+      if (model.ClassLabels != null) {
+        output.Write("label");
+        for (int i = 0; i < nr_class; i++)
+          output.Write(" " + model.ClassLabels[i]);
+        output.Write(Environment.NewLine);
+      }
+
+      if (model.PairwiseProbabilityA != null)
+      // regression has probA only
+            {
+        output.Write("probA");
+        for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
+          output.Write(" " + model.PairwiseProbabilityA[i].ToString("r"));
+        output.Write(Environment.NewLine);
+      }
+      if (model.PairwiseProbabilityB != null) {
+        output.Write("probB");
+        for (int i = 0; i < nr_class * (nr_class - 1) / 2; i++)
+          output.Write(" " + model.PairwiseProbabilityB[i].ToString("r"));
+        output.Write(Environment.NewLine);
+      }
+
+      if (model.NumberOfSVPerClass != null) {
+        output.Write("nr_sv");
+        for (int i = 0; i < nr_class; i++)
+          output.Write(" " + model.NumberOfSVPerClass[i].ToString("r"));
+        output.Write(Environment.NewLine);
+      }
+
+      output.WriteLine("SV");
+      double[][] sv_coef = model.SupportVectorCoefficients;
+      Node[][] SV = model.SupportVectors;
+
+      for (int i = 0; i < l; i++) {
+        for (int j = 0; j < nr_class - 1; j++)
+          output.Write(sv_coef[j][i].ToString("r") + " ");
+
+        Node[] p = SV[i];
+        if (p.Length == 0) {
+          output.WriteLine();
+          continue;
+        }
+        if (param.KernelType == KernelType.PRECOMPUTED)
+          output.Write("0:{0}", (int)p[0].Value);
+        else {
+          output.Write("{0}:{1}", p[0].Index, p[0].Value.ToString("r"));
+          for (int j = 1; j < p.Length; j++)
+            output.Write(" {0}:{1}", p[j].Index, p[j].Value.ToString("r"));
+        }
+        output.WriteLine();
+      }
+
+      output.Flush();
+
+      TemporaryCulture.Stop();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Node.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Node.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Node.cs	(revision 3842)
@@ -0,0 +1,103 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+
+namespace SVM
+{
+    /// <summary>
+    /// Encapsulates a node in a Problem vector, with an index and a value (for more efficient representation
+    /// of sparse data.
+    /// </summary>
+	[Serializable]
+	public class Node : IComparable<Node>
+	{
+        internal int _index;
+        internal double _value;
+
+        /// <summary>
+        /// Default Constructor.
+        /// </summary>
+        public Node()
+        {
+        }
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="index">The index of the value.</param>
+        /// <param name="value">The value to store.</param>
+        public Node(int index, double value)
+        {
+            _index = index;
+            _value = value;
+        }
+
+        /// <summary>
+        /// Index of this Node.
+        /// </summary>
+        public int Index
+        {
+            get
+            {
+                return _index;
+            }
+            set
+            {
+                _index = value;
+            }
+        }
+        /// <summary>
+        /// Value at Index.
+        /// </summary>
+        public double Value
+        {
+            get
+            {
+                return _value;
+            }
+            set
+            {
+                _value = value;
+            }
+        }
+
+        /// <summary>
+        /// String representation of this Node as {index}:{value}.
+        /// </summary>
+        /// <returns>{index}:{value}</returns>
+        public override string ToString()
+        {
+            return string.Format("{0}:{1}", _index, _value);
+        }
+
+        #region IComparable<Node> Members
+
+        /// <summary>
+        /// Compares this node with another.
+        /// </summary>
+        /// <param name="other">The node to compare to</param>
+        /// <returns>A positive number if this node is greater, a negative number if it is less than, or 0 if equal</returns>
+        public int CompareTo(Node other)
+        {
+            return _index.CompareTo(other._index);
+        }
+
+        #endregion
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Parameter.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Parameter.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Parameter.cs	(revision 3842)
@@ -0,0 +1,315 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace SVM
+{
+    /// <summary>
+    /// Contains all of the types of SVM this library can model.
+    /// </summary>
+    public enum SvmType { 
+        /// <summary>
+        /// C-SVC.
+        /// </summary>
+        C_SVC, 
+        /// <summary>
+        /// nu-SVC.
+        /// </summary>
+        NU_SVC, 
+        /// <summary>
+        /// one-class SVM
+        /// </summary>
+        ONE_CLASS, 
+        /// <summary>
+        /// epsilon-SVR
+        /// </summary>
+        EPSILON_SVR, 
+        /// <summary>
+        /// nu-SVR
+        /// </summary>
+        NU_SVR 
+    };
+    /// <summary>
+    /// Contains the various kernel types this library can use.
+    /// </summary>
+    public enum KernelType { 
+        /// <summary>
+        /// Linear: u'*v
+        /// </summary>
+        LINEAR, 
+        /// <summary>
+        /// Polynomial: (gamma*u'*v + coef0)^degree
+        /// </summary>
+        POLY, 
+        /// <summary>
+        /// Radial basis function: exp(-gamma*|u-v|^2)
+        /// </summary>
+        RBF, 
+        /// <summary>
+        /// Sigmoid: tanh(gamma*u'*v + coef0)
+        /// </summary>
+        SIGMOID,
+        /// <summary>
+        /// Precomputed kernel
+        /// </summary>
+        PRECOMPUTED,
+    };
+
+    /// <summary>
+    /// This class contains the various parameters which can affect the way in which an SVM
+    /// is learned.  Unless you know what you are doing, chances are you are best off using
+    /// the default values.
+    /// </summary>
+	[Serializable]
+	public class Parameter : ICloneable
+	{
+        private SvmType _svmType;
+        private KernelType _kernelType;
+        private int _degree;
+        private double _gamma;
+        private double _coef0;
+
+        private double _cacheSize;
+        private double _C;
+        private double _eps;
+
+        private Dictionary<int, double> _weights;
+        private double _nu;
+        private double _p;
+        private bool _shrinking;
+        private bool _probability;
+
+        /// <summary>
+        /// Default Constructor.  Gives good default values to all parameters.
+        /// </summary>
+        public Parameter()
+        {
+            _svmType = SvmType.C_SVC;
+            _kernelType = KernelType.RBF;
+            _degree = 3;
+            _gamma = 0; // 1/k
+            _coef0 = 0;
+            _nu = 0.5;
+            _cacheSize = 40;
+            _C = 1;
+            _eps = 1e-3;
+            _p = 0.1;
+            _shrinking = true;
+            _probability = false;
+            _weights = new Dictionary<int, double>();
+        }
+
+        /// <summary>
+        /// Type of SVM (default C-SVC)
+        /// </summary>
+        public SvmType SvmType
+        {
+            get
+            {
+                return _svmType;
+            }
+            set
+            {
+                _svmType = value;
+            }
+        }
+        /// <summary>
+        /// Type of kernel function (default Polynomial)
+        /// </summary>
+        public KernelType KernelType
+        {
+            get
+            {
+                return _kernelType;
+            }
+            set
+            {
+                _kernelType = value;
+            }
+        }
+        /// <summary>
+        /// Degree in kernel function (default 3).
+        /// </summary>
+        public int Degree
+        {
+            get
+            {
+                return _degree;
+            }
+            set
+            {
+                _degree = value;
+            }
+        }
+        /// <summary>
+        /// Gamma in kernel function (default 1/k)
+        /// </summary>
+        public double Gamma
+        {
+            get
+            {
+                return _gamma;
+            }
+            set
+            {
+                _gamma = value;
+            }
+        }
+        /// <summary>
+        /// Zeroeth coefficient in kernel function (default 0)
+        /// </summary>
+        public double Coefficient0
+        {
+            get
+            {
+                return _coef0;
+            }
+            set
+            {
+                _coef0 = value;
+            }
+        }
+		
+        /// <summary>
+        /// Cache memory size in MB (default 100)
+        /// </summary>
+        public double CacheSize
+        {
+            get
+            {
+                return _cacheSize;
+            }
+            set
+            {
+                _cacheSize = value;
+            }
+        }
+        /// <summary>
+        /// Tolerance of termination criterion (default 0.001)
+        /// </summary>
+        public double EPS
+        {
+            get
+            {
+                return _eps;
+            }
+            set
+            {
+                _eps = value;
+            }
+        }
+        /// <summary>
+        /// The parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
+        /// </summary>
+        public double C
+        {
+            get
+            {
+                return _C;
+            }
+            set
+            {
+                _C = value;
+            }
+        }
+
+        /// <summary>
+        /// Contains custom weights for class labels.  Default weight value is 1.
+        /// </summary>
+        public Dictionary<int,double> Weights
+        {
+            get{
+                return _weights;
+            }
+        }
+
+        /// <summary>
+        /// The parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
+        /// </summary>
+        public double Nu
+        {
+            get
+            {
+                return _nu;
+            }
+            set
+            {
+                _nu = value;
+            }
+        }
+        /// <summary>
+        /// The epsilon in loss function of epsilon-SVR (default 0.1)
+        /// </summary>
+        public double P
+        {
+            get
+            {
+                return _p;
+            }
+            set
+            {
+                _p = value;
+            }
+        }
+        /// <summary>
+        /// Whether to use the shrinking heuristics, (default True)
+        /// </summary>
+        public bool Shrinking
+        {
+            get
+            {
+                return _shrinking;
+            }
+            set
+            {
+                _shrinking = value;
+            }
+        }
+        /// <summary>
+        /// Whether to train an SVC or SVR model for probability estimates, (default False)
+        /// </summary>
+        public bool Probability
+        {
+            get
+            {
+                return _probability;
+            }
+            set
+            {
+                _probability = value;
+            }
+        }
+
+
+        #region ICloneable Members
+        /// <summary>
+        /// Creates a memberwise clone of this parameters object.
+        /// </summary>
+        /// <returns>The clone (as type Parameter)</returns>
+        public object Clone()
+        {
+            return base.MemberwiseClone();
+        }
+
+        #endregion
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/ParameterSelection.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/ParameterSelection.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/ParameterSelection.cs	(revision 3842)
@@ -0,0 +1,239 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace SVM
+{
+    /// <summary>
+    /// This class contains routines which perform parameter selection for a model which uses C-SVC and
+    /// an RBF kernel.
+    /// </summary>
+    public static class ParameterSelection
+    {
+        /// <summary>
+        /// Default number of times to divide the data.
+        /// </summary>
+        public const int NFOLD = 5;
+        /// <summary>
+        /// Default minimum power of 2 for the C value (-5)
+        /// </summary>
+        public const int MIN_C = -5;
+        /// <summary>
+        /// Default maximum power of 2 for the C value (15)
+        /// </summary>
+        public const int MAX_C = 15;
+        /// <summary>
+        /// Default power iteration step for the C value (2)
+        /// </summary>
+        public const int C_STEP = 2;
+        /// <summary>
+        /// Default minimum power of 2 for the Gamma value (-15)
+        /// </summary>
+        public const int MIN_G = -15;
+        /// <summary>
+        /// Default maximum power of 2 for the Gamma Value (3)
+        /// </summary>
+        public const int MAX_G = 3;
+        /// <summary>
+        /// Default power iteration step for the Gamma value (2)
+        /// </summary>
+        public const int G_STEP = 2;
+
+        /// <summary>
+        /// Returns a logarithmic list of values from minimum power of 2 to the maximum power of 2 using the provided iteration size.
+        /// </summary>
+        /// <param name="minPower">The minimum power of 2</param>
+        /// <param name="maxPower">The maximum power of 2</param>
+        /// <param name="iteration">The iteration size to use in powers</param>
+        /// <returns></returns>
+        public static List<double> GetList(double minPower, double maxPower, double iteration)
+        {
+            List<double> list = new List<double>();
+            for (double d = minPower; d <= maxPower; d += iteration)
+                list.Add(Math.Pow(2, d));
+            return list;
+        }
+
+        /// <summary>
+        /// Performs a Grid parameter selection, trying all possible combinations of the two lists and returning the
+        /// combination which performed best.  The default ranges of C and Gamma values are used.  Use this method if there is no validation data available, and it will
+        /// divide it 5 times to allow 5-fold validation (training on 4/5 and validating on 1/5, 5 times).
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="parameters">The parameters to use when optimizing</param>
+        /// <param name="outputFile">Output file for the parameter results.</param>
+        /// <param name="C">The optimal C value will be put into this variable</param>
+        /// <param name="Gamma">The optimal Gamma value will be put into this variable</param>
+        public static void Grid(
+            Problem problem,
+            Parameter parameters,
+            string outputFile,
+            out double C,
+            out double Gamma)
+        {
+            Grid(problem, parameters, GetList(MIN_C, MAX_C, C_STEP), GetList(MIN_G, MAX_G, G_STEP), outputFile, NFOLD, out C, out Gamma);
+        }
+        /// <summary>
+        /// Performs a Grid parameter selection, trying all possible combinations of the two lists and returning the
+        /// combination which performed best.  Use this method if there is no validation data available, and it will
+        /// divide it 5 times to allow 5-fold validation (training on 4/5 and validating on 1/5, 5 times).
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="parameters">The parameters to use when optimizing</param>
+        /// <param name="CValues">The set of C values to use</param>
+        /// <param name="GammaValues">The set of Gamma values to use</param>
+        /// <param name="outputFile">Output file for the parameter results.</param>
+        /// <param name="C">The optimal C value will be put into this variable</param>
+        /// <param name="Gamma">The optimal Gamma value will be put into this variable</param>
+        public static void Grid(
+            Problem problem,
+            Parameter parameters,
+            List<double> CValues,
+            List<double> GammaValues,
+            string outputFile,
+            out double C,
+            out double Gamma)
+        {
+            Grid(problem, parameters, CValues, GammaValues, outputFile, NFOLD, out C, out Gamma);
+        }
+        /// <summary>
+        /// Performs a Grid parameter selection, trying all possible combinations of the two lists and returning the
+        /// combination which performed best.  Use this method if validation data isn't available, as it will
+        /// divide the training data and train on a portion of it and test on the rest.
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="parameters">The parameters to use when optimizing</param>
+        /// <param name="CValues">The set of C values to use</param>
+        /// <param name="GammaValues">The set of Gamma values to use</param>
+        /// <param name="outputFile">Output file for the parameter results.</param>
+        /// <param name="nrfold">The number of times the data should be divided for validation</param>
+        /// <param name="C">The optimal C value will be placed in this variable</param>
+        /// <param name="Gamma">The optimal Gamma value will be placed in this variable</param>
+        public static void Grid(
+            Problem problem,
+            Parameter parameters,
+            List<double> CValues, 
+            List<double> GammaValues, 
+            string outputFile,
+            int nrfold,
+            out double C,
+            out double Gamma)
+        {
+            C = 0;
+            Gamma = 0;
+            double crossValidation = double.MinValue;
+            StreamWriter output = null;
+            if(outputFile != null)
+                output = new StreamWriter(outputFile);
+            for(int i=0; i<CValues.Count; i++)
+                for (int j = 0; j < GammaValues.Count; j++)
+                {
+                    parameters.C = CValues[i];
+                    parameters.Gamma = GammaValues[j];
+                    double test = Training.PerformCrossValidation(problem, parameters, nrfold);
+                    Console.Write("{0} {1} {2}", parameters.C, parameters.Gamma, test);
+                    if(output != null)
+                        output.WriteLine("{0} {1} {2}", parameters.C, parameters.Gamma, test);
+                    if (test > crossValidation)
+                    {
+                        C = parameters.C;
+                        Gamma = parameters.Gamma;
+                        crossValidation = test;
+                        Console.WriteLine(" New Maximum!");
+                    }
+                    else Console.WriteLine();
+                }
+            if(output != null)
+                output.Close();
+        }
+        /// <summary>
+        /// Performs a Grid parameter selection, trying all possible combinations of the two lists and returning the
+        /// combination which performed best.  Uses the default values of C and Gamma.
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="validation">The validation data</param>
+        /// <param name="parameters">The parameters to use when optimizing</param>
+        /// <param name="outputFile">The output file for the parameter results</param>
+        /// <param name="C">The optimal C value will be placed in this variable</param>
+        /// <param name="Gamma">The optimal Gamma value will be placed in this variable</param>
+        public static void Grid(
+            Problem problem,
+            Problem validation,
+            Parameter parameters,
+            string outputFile,
+            out double C,
+            out double Gamma)
+        {
+            Grid(problem, validation, parameters, GetList(MIN_C, MAX_C, C_STEP), GetList(MIN_G, MAX_G, G_STEP), outputFile, out C, out Gamma);
+        }
+        /// <summary>
+        /// Performs a Grid parameter selection, trying all possible combinations of the two lists and returning the
+        /// combination which performed best.
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="validation">The validation data</param>
+        /// <param name="parameters">The parameters to use when optimizing</param>
+        /// <param name="CValues">The C values to use</param>
+        /// <param name="GammaValues">The Gamma values to use</param>
+        /// <param name="outputFile">The output file for the parameter results</param>
+        /// <param name="C">The optimal C value will be placed in this variable</param>
+        /// <param name="Gamma">The optimal Gamma value will be placed in this variable</param>
+        public static void Grid(
+            Problem problem,
+            Problem validation,
+            Parameter parameters,
+            List<double> CValues,
+            List<double> GammaValues,
+            string outputFile,
+            out double C,
+            out double Gamma)
+        {
+            C = 0;
+            Gamma = 0;
+            double maxScore = double.MinValue;
+            StreamWriter output = null;
+            if(outputFile != null)
+                output = new StreamWriter(outputFile);
+            for (int i = 0; i < CValues.Count; i++)
+                for (int j = 0; j < GammaValues.Count; j++)
+                {
+                    parameters.C = CValues[i];
+                    parameters.Gamma = GammaValues[j];
+                    Model model = Training.Train(problem, parameters);
+                    double test = Prediction.Predict(validation, "tmp.txt", model, false);
+                    Console.Write("{0} {1} {2}", parameters.C, parameters.Gamma, test);
+                    if(output != null)
+                        output.WriteLine("{0} {1} {2}", parameters.C, parameters.Gamma, test);
+                    if (test > maxScore)
+                    {
+                        C = parameters.C;
+                        Gamma = parameters.Gamma;
+                        maxScore = test;
+                        Console.WriteLine(" New Maximum!");
+                    }
+                    else Console.WriteLine();
+                }
+            if(output != null)
+                output.Close();
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/PerformanceEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/PerformanceEvaluator.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/PerformanceEvaluator.cs	(revision 3842)
@@ -0,0 +1,415 @@
+﻿/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Globalization;
+
+namespace SVM
+{
+    /// <summary>
+    /// Class encoding a member of a ranked set of labels.
+    /// </summary>
+    public class RankPair : IComparable<RankPair>
+    {
+        private double _score, _label;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="score">Score for this pair</param>
+        /// <param name="label">Label associated with the given score</param>
+        public RankPair(double score, double label)
+        {
+            _score = score;
+            _label = label;
+        }
+
+        /// <summary>
+        /// The score for this pair.
+        /// </summary>
+        public double Score
+        {
+            get
+            {
+                return _score;
+            }
+        }
+
+        /// <summary>
+        /// The Label for this pair.
+        /// </summary>
+        public double Label
+        {
+            get
+            {
+                return _label;
+            }
+        }
+
+        #region IComparable<RankPair> Members
+
+        /// <summary>
+        /// Compares this pair to another.  It will end up in a sorted list in decending score order.
+        /// </summary>
+        /// <param name="other">The pair to compare to</param>
+        /// <returns>Whether this should come before or after the argument</returns>
+        public int CompareTo(RankPair other)
+        {
+            return other.Score.CompareTo(Score);
+        }
+
+        #endregion
+
+        /// <summary>
+        /// Returns a string representation of this pair.
+        /// </summary>
+        /// <returns>A string in the for Score:Label</returns>
+        public override string ToString()
+        {
+            return string.Format("{0}:{1}", Score, Label);
+        }
+    }
+
+    /// <summary>
+    /// Class encoding the point on a 2D curve.
+    /// </summary>
+    public class CurvePoint
+    {
+        private float _x, _y;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="x">X coordinate</param>
+        /// <param name="y">Y coordinate</param>
+        public CurvePoint(float x, float y)
+        {
+            _x = x;
+            _y = y;
+        }
+
+        /// <summary>
+        /// X coordinate
+        /// </summary>
+        public float X
+        {
+            get
+            {
+                return _x;
+            }
+        }
+
+        /// <summary>
+        /// Y coordinate
+        /// </summary>
+        public float Y
+        {
+            get
+            {
+                return _y;
+            }
+        }
+
+        /// <summary>
+        /// Creates a string representation of this point.
+        /// </summary>
+        /// <returns>string in the form (x, y)</returns>
+        public override string ToString()
+        {
+            return string.Format("({0}, {1})", _x, _y);
+        }
+    }
+
+    /// <summary>
+    /// Class which evaluates an SVM model using several standard techniques.
+    /// </summary>
+    public class PerformanceEvaluator
+    {
+        private class ChangePoint
+        {
+            public ChangePoint(int tp, int fp, int tn, int fn)
+            {
+                TP = tp;
+                FP = fp;
+                TN = tn;
+                FN = fn;
+            }
+
+            public int TP, FP, TN, FN;
+
+            public override string ToString()
+            {
+                return string.Format("{0}:{1}:{2}:{3}", TP, FP, TN, FN);
+            }
+        }
+
+        private List<CurvePoint> _prCurve;
+        private double _ap;
+
+        private List<CurvePoint> _rocCurve;
+        private double _auc;
+
+        private List<RankPair> _data;
+        private List<ChangePoint> _changes;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="set">A pre-computed ranked pair set</param>
+        public PerformanceEvaluator(List<RankPair> set)
+        {
+            _data = set;
+            computeStatistics();
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="model">Model to evaluate</param>
+        /// <param name="problem">Problem to evaluate</param>
+        /// <param name="category">Label to be evaluate for</param>
+        public PerformanceEvaluator(Model model, Problem problem, double category) : this(model, problem, category, "tmp.results") { }
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="model">Model to evaluate</param>
+        /// <param name="problem">Problem to evaluate</param>
+        /// <param name="resultsFile">Results file for output</param>
+        /// <param name="category">Category to evaluate for</param>
+        public PerformanceEvaluator(Model model, Problem problem, double category, string resultsFile)
+        {
+            Prediction.Predict(problem, resultsFile, model, true);
+            parseResultsFile(resultsFile, problem.Y, category);
+
+            computeStatistics();
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="resultsFile">Results file</param>
+        /// <param name="correctLabels">The correct labels of each data item</param>
+        /// <param name="category">The category to evaluate for</param>
+        public PerformanceEvaluator(string resultsFile, double[] correctLabels, double category)
+        {
+            parseResultsFile(resultsFile, correctLabels, category);
+            computeStatistics();
+        }
+
+        private void parseResultsFile(string resultsFile, double[] labels, double category)
+        {
+            StreamReader input = new StreamReader(resultsFile);
+            string[] parts = input.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+            int confidenceIndex = -1;
+            for (int i = 1; i < parts.Length; i++)
+                if (double.Parse(parts[i], CultureInfo.InvariantCulture) == category)
+                {
+                    confidenceIndex = i;
+                    break;
+                }
+            _data = new List<RankPair>();
+            for (int i = 0; i < labels.Length; i++)
+            {
+                parts = input.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+                double confidence = double.Parse(parts[confidenceIndex], CultureInfo.InvariantCulture);
+                _data.Add(new RankPair(confidence, labels[i] == category ? 1 : 0));
+            }
+            input.Close();
+        }
+
+        private void computeStatistics()
+        {
+            _data.Sort();
+
+            findChanges();
+            computePR();
+            computeRoC();
+        }
+
+        private void findChanges()
+        {
+            int tp, fp, tn, fn;
+            tp = fp = tn = fn = 0;
+            for (int i = 0; i < _data.Count; i++)
+            {
+                if (_data[i].Label == 1)
+                    fn++;
+                else tn++;
+            }
+            _changes = new List<ChangePoint>();
+            for (int i = 0; i < _data.Count; i++)
+            {
+                if (_data[i].Label == 1)
+                {
+                    tp++;
+                    fn--;
+                }
+                else
+                {
+                    fp++;
+                    tn--;
+                }
+                _changes.Add(new ChangePoint(tp, fp, tn, fn));
+            }
+        }
+
+        private float computePrecision(ChangePoint p)
+        {
+            return (float)p.TP / (p.TP + p.FP);
+        }
+
+        private float computeRecall(ChangePoint p)
+        {
+            return (float)p.TP / (p.TP + p.FN);
+        }
+
+        private void computePR()
+        {
+            _prCurve = new List<CurvePoint>();
+            _prCurve.Add(new CurvePoint(0, 1));
+            float precision = computePrecision(_changes[0]);
+            float recall = computeRecall(_changes[0]);
+            float precisionSum = 0;
+            if (_changes[0].TP > 0)
+            {
+                precisionSum += precision;
+                _prCurve.Add(new CurvePoint(recall, precision));
+            }
+            for (int i = 1; i < _changes.Count; i++)
+            {
+                precision = computePrecision(_changes[i]);
+                recall = computeRecall(_changes[i]);
+                if (_changes[i].TP > _changes[i - 1].TP)
+                {
+                    precisionSum += precision;
+                    _prCurve.Add(new CurvePoint(recall, precision));
+                }
+            }
+            _prCurve.Add(new CurvePoint(1, (float)(_changes[0].TP + _changes[0].FN) / (_changes[0].FP + _changes[0].TN)));
+            _ap = precisionSum / (_changes[0].FN + _changes[0].TP);
+        }
+
+        /// <summary>
+        /// Writes the Precision-Recall curve to a tab-delimited file.
+        /// </summary>
+        /// <param name="filename">Filename for output</param>
+        public void WritePRCurve(string filename)
+        {
+            StreamWriter output = new StreamWriter(filename);
+            output.WriteLine(_ap);
+            for (int i = 0; i < _prCurve.Count; i++)
+                output.WriteLine("{0}\t{1}", _prCurve[i].X, _prCurve[i].Y);
+            output.Close();
+        }
+
+        /// <summary>
+        /// Writes the Receiver Operating Characteristic curve to a tab-delimited file.
+        /// </summary>
+        /// <param name="filename">Filename for output</param>
+        public void WriteROCCurve(string filename)
+        {
+            StreamWriter output = new StreamWriter(filename);
+            output.WriteLine(_auc);
+            for (int i = 0; i < _rocCurve.Count; i++)
+                output.WriteLine("{0}\t{1}", _rocCurve[i].X, _rocCurve[i].Y);
+            output.Close();
+        }
+
+        /// <summary>
+        /// Receiver Operating Characteristic curve
+        /// </summary>
+        public List<CurvePoint> ROCCurve
+        {
+            get
+            {
+                return _rocCurve;
+            }
+        }
+
+        /// <summary>
+        /// Returns the area under the ROC Curve
+        /// </summary>
+        public double AuC
+        {
+            get
+            {
+                return _auc;
+            }
+        }
+
+        /// <summary>
+        /// Precision-Recall curve
+        /// </summary>
+        public List<CurvePoint> PRCurve
+        {
+            get
+            {
+                return _prCurve;
+            }
+        }
+
+        /// <summary>
+        /// The average precision
+        /// </summary>
+        public double AP
+        {
+            get
+            {
+                return _ap;
+            }
+        }
+
+        private float computeTPR(ChangePoint cp)
+        {
+            return computeRecall(cp);
+        }
+
+        private float computeFPR(ChangePoint cp)
+        {
+            return (float)cp.FP / (cp.FP + cp.TN);
+        }
+
+        private void computeRoC()
+        {
+            _rocCurve = new List<CurvePoint>();
+            _rocCurve.Add(new CurvePoint(0, 0));
+            float tpr = computeTPR(_changes[0]);
+            float fpr = computeFPR(_changes[0]);
+            _rocCurve.Add(new CurvePoint(fpr, tpr));
+            _auc = 0;
+            for (int i = 1; i < _changes.Count; i++)
+            {
+                float newTPR = computeTPR(_changes[i]);
+                float newFPR = computeFPR(_changes[i]);
+                if (_changes[i].TP > _changes[i - 1].TP)
+                {
+                    _auc += tpr * (newFPR - fpr) + .5 * (newTPR - tpr) * (newFPR - fpr);
+                    tpr = newTPR;
+                    fpr = newFPR;
+                    _rocCurve.Add(new CurvePoint(fpr, tpr));
+                }
+            }
+            _rocCurve.Add(new CurvePoint(1, 1));
+            _auc += tpr * (1 - fpr) + .5 * (1 - tpr) * (1 - fpr);
+        }
+
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/PrecomputedKernel.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/PrecomputedKernel.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/PrecomputedKernel.cs	(revision 3842)
@@ -0,0 +1,117 @@
+﻿/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Collections.Generic;
+
+namespace SVM
+{
+    /// <summary>
+    /// Class encapsulating a precomputed kernel, where each position indicates the similarity score for two items in the training data.
+    /// </summary>
+    [Serializable]
+    public class PrecomputedKernel
+    {
+        private float[,] _similarities;
+        private int _rows;
+        private int _columns;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="similarities">The similarity scores between all items in the training data</param>
+        public PrecomputedKernel(float[,] similarities)
+        {
+            _similarities = similarities;
+            _rows = _similarities.GetLength(0);
+            _columns = _similarities.GetLength(1);
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="nodes">Nodes for self-similarity analysis</param>
+        /// <param name="param">Parameters to use when computing similarities</param>
+        public PrecomputedKernel(List<Node[]> nodes, Parameter param)
+        {
+            _rows = nodes.Count;
+            _columns = _rows;
+            _similarities = new float[_rows, _columns];
+            for (int r = 0; r < _rows; r++)
+            {
+                for (int c = 0; c < r; c++)
+                    _similarities[r, c] = _similarities[c, r];
+                _similarities[r, r] = 1;
+                for (int c = r + 1; c < _columns; c++)
+                    _similarities[r, c] = (float)Kernel.KernelFunction(nodes[r], nodes[c], param);
+            }
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="rows">Nodes to use as the rows of the matrix</param>
+        /// <param name="columns">Nodes to use as the columns of the matrix</param>
+        /// <param name="param">Parameters to use when compute similarities</param>
+        public PrecomputedKernel(List<Node[]> rows, List<Node[]> columns, Parameter param)
+        {
+            _rows = rows.Count;
+            _columns = columns.Count;
+            _similarities = new float[_rows, _columns];
+            for (int r = 0; r < _rows; r++)
+                for (int c = 0; c < _columns; c++)
+                    _similarities[r, c] = (float)Kernel.KernelFunction(rows[r], columns[c], param);
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="Problem"/> object using the labels provided.  If a label is set to "0" that item is ignored.
+        /// </summary>
+        /// <param name="rowLabels">The labels for the row items</param>
+        /// <param name="columnLabels">The labels for the column items</param>
+        /// <returns>A <see cref="Problem"/> object</returns>
+        public Problem Compute(double[] rowLabels, double[] columnLabels)
+        {
+            List<Node[]> X = new List<Node[]>();
+            List<double> Y = new List<double>();
+            int maxIndex = 0;
+            for (int i = 0; i < columnLabels.Length; i++)
+                if (columnLabels[i] != 0)
+                    maxIndex++;
+            maxIndex++;
+            for (int r = 0; r < _rows; r++)
+            {
+                if (rowLabels[r] == 0)
+                    continue;
+                List<Node> nodes = new List<Node>();
+                nodes.Add(new Node(0, X.Count + 1));
+                for (int c = 0; c < _columns; c++)
+                {
+                    if (columnLabels[c] == 0)
+                        continue;
+                    double value = _similarities[r, c];
+                    nodes.Add(new Node(nodes.Count, value));
+                }
+                X.Add(nodes.ToArray());
+                Y.Add(rowLabels[r]);
+            }
+            return new Problem(X.Count, Y.ToArray(), X.ToArray(), maxIndex);
+        }
+
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Prediction.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Prediction.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Prediction.cs	(revision 3842)
@@ -0,0 +1,188 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace SVM
+{
+    /// <summary>
+    /// Class containing the routines to perform class membership prediction using a trained SVM.
+    /// </summary>
+    public static class Prediction
+    {
+        /// <summary>
+        /// Predicts the class memberships of all the vectors in the problem.
+        /// </summary>
+        /// <param name="problem">The SVM Problem to solve</param>
+        /// <param name="outputFile">File for result output</param>
+        /// <param name="model">The Model to use</param>
+        /// <param name="predict_probability">Whether to output a distribution over the classes</param>
+        /// <returns>Percentage correctly labelled</returns>
+        public static double Predict(
+            Problem problem,
+            string outputFile,
+            Model model,
+            bool predict_probability)
+        {
+            int correct = 0;
+            int total = 0;
+            double error = 0;
+            double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
+            StreamWriter output = outputFile != null ? new StreamWriter(outputFile) : null;
+
+            SvmType svm_type = Procedures.svm_get_svm_type(model);
+            int nr_class = Procedures.svm_get_nr_class(model);
+            int[] labels = new int[nr_class];
+            double[] prob_estimates = null;
+
+            if (predict_probability)
+            {
+                if (svm_type == SvmType.EPSILON_SVR || svm_type == SvmType.NU_SVR)
+                {
+                    Console.WriteLine("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=" + Procedures.svm_get_svr_probability(model));
+                }
+                else
+                {
+                    Procedures.svm_get_labels(model, labels);
+                    prob_estimates = new double[nr_class];
+                    if (output != null)
+                    {
+                        output.Write("labels");
+                        for (int j = 0; j < nr_class; j++)
+                        {
+                            output.Write(" " + labels[j]);
+                        }
+                        output.Write("\n");
+                    }
+                }
+            }
+            for (int i = 0; i < problem.Count; i++)
+            {
+                double target = problem.Y[i];
+                Node[] x = problem.X[i];
+
+                double v;
+                if (predict_probability && (svm_type == SvmType.C_SVC || svm_type == SvmType.NU_SVC))
+                {
+                    v = Procedures.svm_predict_probability(model, x, prob_estimates);
+                    if (output != null)
+                    {
+                        output.Write(v + " ");
+                        for (int j = 0; j < nr_class; j++)
+                        {
+                            output.Write(prob_estimates[j] + " ");
+                        }
+                        output.Write("\n");
+                    }
+                }
+                else
+                {
+                    v = Procedures.svm_predict(model, x);
+                    if(output != null)
+                        output.Write(v + "\n");
+                }
+
+                if (v == target)
+                    ++correct;
+                error += (v - target) * (v - target);
+                sumv += v;
+                sumy += target;
+                sumvv += v * v;
+                sumyy += target * target;
+                sumvy += v * target;
+                ++total;
+            }
+            if(output != null)
+                output.Close();
+            return (double)correct / total;
+        }
+
+        /// <summary>
+        /// Predict the class for a single input vector.
+        /// </summary>
+        /// <param name="model">The Model to use for prediction</param>
+        /// <param name="x">The vector for which to predict class</param>
+        /// <returns>The result</returns>
+        public static double Predict(Model model, Node[] x)
+        {
+            return Procedures.svm_predict(model, x);
+        }
+
+        /// <summary>
+        /// Predicts a class distribution for the single input vector.
+        /// </summary>
+        /// <param name="model">Model to use for prediction</param>
+        /// <param name="x">The vector for which to predict the class distribution</param>
+        /// <returns>A probability distribtion over classes</returns>
+        public static double[] PredictProbability(Model model, Node[] x)
+        {
+            SvmType svm_type = Procedures.svm_get_svm_type(model);
+            if (svm_type != SvmType.C_SVC && svm_type != SvmType.NU_SVC)
+                throw new Exception("Model type " + svm_type + " unable to predict probabilities.");
+            int nr_class = Procedures.svm_get_nr_class(model);
+            double[] probEstimates = new double[nr_class];
+            Procedures.svm_predict_probability(model, x, probEstimates);
+            return probEstimates;
+        }
+
+        private static void exit_with_help()
+        {
+            Debug.Write("usage: svm_predict [options] test_file model_file output_file\n" + "options:\n" + "-b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0); one-class SVM not supported yet\n");
+            Environment.Exit(1);
+        }
+
+        /// <summary>
+        /// Legacy method, provided to allow usage as though this were the command line version of libsvm.
+        /// </summary>
+        /// <param name="args">Standard arguments passed to the svm_predict exectutable.  See libsvm documentation for details.</param>
+        [Obsolete("Use the other version of Predict() instead")]
+        public static void Predict(params string[] args)
+        {
+            int i = 0;
+            bool predictProbability = false;
+
+            // parse options
+            for (i = 0; i < args.Length; i++)
+            {
+                if (args[i][0] != '-')
+                    break;
+                ++i;
+                switch (args[i - 1][1])
+                {
+
+                    case 'b':
+                        predictProbability = int.Parse(args[i]) == 1;
+                        break;
+
+                    default:
+                        throw new ArgumentException("Unknown option");
+
+                }
+            }
+            if (i >= args.Length)
+                throw new ArgumentException("No input, model and output files provided");
+
+            Problem problem = Problem.Read(args[i]);
+            Model model = Model.Read(args[i + 1]);
+            Predict(problem, args[i + 2], model, predictProbability);
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Problem.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Problem.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Problem.cs	(revision 3842)
@@ -0,0 +1,212 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Threading;
+using System.Globalization;
+
+namespace SVM
+{
+    /// <summary>
+    /// Encapsulates a problem, or set of vectors which must be classified.
+    /// </summary>
+	[Serializable]
+	public class Problem
+	{
+        private int _count;
+        private double[] _Y;
+        private Node[][] _X;
+        private int _maxIndex;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="count">Number of vectors</param>
+        /// <param name="y">The class labels</param>
+        /// <param name="x">Vector data.</param>
+        /// <param name="maxIndex">Maximum index for a vector</param>
+        public Problem(int count, double[] y, Node[][] x, int maxIndex)
+        {
+            _count = count;
+            _Y = y;
+            _X = x;
+            _maxIndex = maxIndex;
+        }
+        /// <summary>
+        /// Empty Constructor.  Nothing is initialized.
+        /// </summary>
+        public Problem()
+        {
+        }
+        /// <summary>
+        /// Number of vectors.
+        /// </summary>
+        public int Count
+        {
+            get
+            {
+                return _count;
+            }
+            set
+            {
+                _count = value;
+            }
+        }
+        /// <summary>
+        /// Class labels.
+        /// </summary>
+        public double[] Y
+        {
+            get
+            {
+                return _Y;
+            }
+            set
+            {
+                _Y = value;
+            }
+        }
+        /// <summary>
+        /// Vector data.
+        /// </summary>
+        public Node[][] X
+        {
+            get
+            {
+                return _X;
+            }
+            set
+            {
+                _X = value;
+            }
+        }
+        /// <summary>
+        /// Maximum index for a vector.
+        /// </summary>
+        public int MaxIndex
+        {
+            get
+            {
+                return _maxIndex;
+            }
+            set
+            {
+                _maxIndex = value;
+            }
+        }
+
+        /// <summary>
+        /// Reads a problem from a stream.
+        /// </summary>
+        /// <param name="stream">Stream to read from</param>
+        /// <returns>The problem</returns>
+        public static Problem Read(Stream stream)
+        {
+            TemporaryCulture.Start();
+
+            StreamReader input = new StreamReader(stream);
+            List<double> vy = new List<double>();
+            List<Node[]> vx = new List<Node[]>();
+            int max_index = 0;
+
+            while (input.Peek() > -1)
+            {
+                string[] parts = input.ReadLine().Trim().Split();
+
+                vy.Add(double.Parse(parts[0]));
+                int m = parts.Length - 1;
+                Node[] x = new Node[m];
+                for (int j = 0; j < m; j++)
+                {
+                    x[j] = new Node();
+                    string[] nodeParts = parts[j + 1].Split(':');
+                    x[j].Index = int.Parse(nodeParts[0]);
+                    x[j].Value = double.Parse(nodeParts[1]);
+                }
+                if (m > 0)
+                    max_index = Math.Max(max_index, x[m - 1].Index);
+                vx.Add(x);
+            }
+
+            TemporaryCulture.Stop();
+
+            return new Problem(vy.Count, vy.ToArray(), vx.ToArray(), max_index);
+        }
+
+        /// <summary>
+        /// Writes a problem to a stream.
+        /// </summary>
+        /// <param name="stream">The stream to write the problem to.</param>
+        /// <param name="problem">The problem to write.</param>
+        public static void Write(Stream stream, Problem problem)
+        {
+            TemporaryCulture.Start();
+
+            StreamWriter output = new StreamWriter(stream);
+            for (int i = 0; i < problem.Count; i++)
+            {
+                output.Write(problem.Y[i]);
+                for (int j = 0; j < problem.X[i].Length; j++)
+                    output.Write(" {0}:{1}", problem.X[i][j].Index, problem.X[i][j].Value);
+                output.WriteLine();
+            }
+            output.Flush();
+
+            TemporaryCulture.Stop();
+        }
+
+        /// <summary>
+        /// Reads a Problem from a file.
+        /// </summary>
+        /// <param name="filename">The file to read from.</param>
+        /// <returns>the Probem</returns>
+        public static Problem Read(string filename)
+        {
+            FileStream input = File.OpenRead(filename);
+            try
+            {
+                return Read(input);
+            }
+            finally
+            {
+                input.Close();
+            }
+        }
+
+        /// <summary>
+        /// Writes a problem to a file.   This will overwrite any previous data in the file.
+        /// </summary>
+        /// <param name="filename">The file to write to</param>
+        /// <param name="problem">The problem to write</param>
+        public static void Write(string filename, Problem problem)
+        {
+            FileStream output = File.Open(filename, FileMode.Create);
+            try
+            {
+                Write(output, problem);
+            }
+            finally
+            {
+                output.Close();
+            }
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Properties/AssemblyInfo.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Properties/AssemblyInfo.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Properties/AssemblyInfo.cs	(revision 3842)
@@ -0,0 +1,35 @@
+﻿using System.Reflection;
+using System.Runtime.CompilerServices;
+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("SVM.NET")]
+[assembly: AssemblyDescription("A .NET Support Vector Machine library adapted from libsvm")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Matthew Johnson")]
+[assembly: AssemblyProduct("SVM.NET")]
+[assembly: AssemblyCopyright("Copyright ©  Matthew Johnson 2009")]
+[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("803d4e74-70db-432e-a4da-32e7a021eec2")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.6.3")]
+[assembly: AssemblyFileVersion("1.6.3")]
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/RangeTransform.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/RangeTransform.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/RangeTransform.cs	(revision 3842)
@@ -0,0 +1,225 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Globalization;
+
+namespace SVM {
+  /// <summary>
+  /// Class which encapsulates a range transformation.
+  /// </summary>
+  public class RangeTransform : IRangeTransform {
+    /// <summary>
+    /// Default lower bound for scaling (-1).
+    /// </summary>
+    public const int DEFAULT_LOWER_BOUND = -1;
+    /// <summary>
+    /// Default upper bound for scaling (1).
+    /// </summary>
+    public const int DEFAULT_UPPER_BOUND = 1;
+
+    /// <summary>
+    /// Determines the Range transform for the provided problem.  Uses the default lower and upper bounds.
+    /// </summary>
+    /// <param name="prob">The Problem to analyze</param>
+    /// <returns>The Range transform for the problem</returns>
+    public static RangeTransform Compute(Problem prob) {
+      return Compute(prob, DEFAULT_LOWER_BOUND, DEFAULT_UPPER_BOUND);
+    }
+    /// <summary>
+    /// Determines the Range transform for the provided problem.
+    /// </summary>
+    /// <param name="prob">The Problem to analyze</param>
+    /// <param name="lowerBound">The lower bound for scaling</param>
+    /// <param name="upperBound">The upper bound for scaling</param>
+    /// <returns>The Range transform for the problem</returns>
+    public static RangeTransform Compute(Problem prob, double lowerBound, double upperBound) {
+      double[] minVals = new double[prob.MaxIndex];
+      double[] maxVals = new double[prob.MaxIndex];
+      for (int i = 0; i < prob.MaxIndex; i++) {
+        minVals[i] = double.MaxValue;
+        maxVals[i] = double.MinValue;
+      }
+      for (int i = 0; i < prob.Count; i++) {
+        for (int j = 0; j < prob.X[i].Length; j++) {
+          int index = prob.X[i][j].Index - 1;
+          double value = prob.X[i][j].Value;
+          minVals[index] = Math.Min(minVals[index], value);
+          maxVals[index] = Math.Max(maxVals[index], value);
+        }
+      }
+      for (int i = 0; i < prob.MaxIndex; i++) {
+        if (minVals[i] == double.MaxValue || maxVals[i] == double.MinValue) {
+          minVals[i] = 0;
+          maxVals[i] = 0;
+        }
+      }
+      return new RangeTransform(minVals, maxVals, lowerBound, upperBound);
+    }
+
+    private double[] _inputStart;
+    private double[] _inputScale;
+    private double _outputStart;
+    private double _outputScale;
+    private int _length;
+
+    /// <summary>
+    /// Constructor.
+    /// </summary>
+    /// <param name="minValues">The minimum values in each dimension.</param>
+    /// <param name="maxValues">The maximum values in each dimension.</param>
+    /// <param name="lowerBound">The desired lower bound for all dimensions.</param>
+    /// <param name="upperBound">The desired upper bound for all dimensions.</param>
+    public RangeTransform(double[] minValues, double[] maxValues, double lowerBound, double upperBound) {
+      _length = minValues.Length;
+      if (maxValues.Length != _length)
+        throw new Exception("Number of max and min values must be equal.");
+      _inputStart = new double[_length];
+      _inputScale = new double[_length];
+      for (int i = 0; i < _length; i++) {
+        _inputStart[i] = minValues[i];
+        _inputScale[i] = maxValues[i] - minValues[i];
+      }
+      _outputStart = lowerBound;
+      _outputScale = upperBound - lowerBound;
+    }
+    private RangeTransform(double[] inputStart, double[] inputScale, double outputStart, double outputScale, int length) {
+      _inputStart = inputStart;
+      _inputScale = inputScale;
+      _outputStart = outputStart;
+      _outputScale = outputScale;
+      _length = length;
+    }
+    /// <summary>
+    /// Transforms the input array based upon the values provided.
+    /// </summary>
+    /// <param name="input">The input array</param>
+    /// <returns>A scaled array</returns>
+    public Node[] Transform(Node[] input) {
+      Node[] output = new Node[input.Length];
+      for (int i = 0; i < output.Length; i++) {
+        int index = input[i].Index;
+        double value = input[i].Value;
+        output[i] = new Node(index, Transform(value, index));
+      }
+      return output;
+    }
+
+    /// <summary>
+    /// Transforms this an input value using the scaling transform for the provided dimension.
+    /// </summary>
+    /// <param name="input">The input value to transform</param>
+    /// <param name="index">The dimension whose scaling transform should be used</param>
+    /// <returns>The scaled value</returns>
+    public double Transform(double input, int index) {
+      index--;
+      double tmp = input - _inputStart[index];
+      if (_inputScale[index] == 0)
+        return 0;
+      tmp /= _inputScale[index];
+      tmp *= _outputScale;
+      return tmp + _outputStart;
+    }
+    /// <summary>
+    /// Writes this Range transform to a stream.
+    /// </summary>
+    /// <param name="stream">The stream to write to</param>
+    /// <param name="r">The range to write</param>
+    public static void Write(Stream stream, RangeTransform r) {
+      TemporaryCulture.Start();
+
+      StreamWriter output = new StreamWriter(stream);
+      output.WriteLine(r._length);
+      output.Write(r._inputStart[0].ToString("r"));
+      for (int i = 1; i < r._inputStart.Length; i++)
+        output.Write(" " + r._inputStart[i].ToString("r"));
+      output.WriteLine();
+      output.Write(r._inputScale[0].ToString("r"));
+      for (int i = 1; i < r._inputScale.Length; i++)
+        output.Write(" " + r._inputScale[i].ToString("r"));
+      output.WriteLine();
+      output.WriteLine("{0} {1}", r._outputStart.ToString("r"), r._outputScale.ToString("r"));
+      output.Flush();
+
+      TemporaryCulture.Stop();
+    }
+
+    /// <summary>
+    /// Writes this Range transform to a file.    This will overwrite any previous data in the file.
+    /// </summary>
+    /// <param name="outputFile">The file to write to</param>
+    /// <param name="r">The Range to write</param>
+    public static void Write(string outputFile, RangeTransform r) {
+      FileStream s = File.Open(outputFile, FileMode.Create);
+      try {
+        Write(s, r);
+      }
+      finally {
+        s.Close();
+      }
+    }
+
+    /// <summary>
+    /// Reads a Range transform from a file.
+    /// </summary>
+    /// <param name="inputFile">The file to read from</param>
+    /// <returns>The Range transform</returns>
+    public static RangeTransform Read(string inputFile) {
+      FileStream s = File.OpenRead(inputFile);
+      try {
+        return Read(s);
+      }
+      finally {
+        s.Close();
+      }
+    }
+
+    /// <summary>
+    /// Reads a Range transform from a stream.
+    /// </summary>
+    /// <param name="stream">The stream to read from</param>
+    /// <returns>The Range transform</returns>
+    public static RangeTransform Read(Stream stream) {
+      return Read(new StreamReader(stream));
+    }
+
+    public static RangeTransform Read(TextReader input) {
+      TemporaryCulture.Start();
+
+      int length = int.Parse(input.ReadLine());
+      double[] inputStart = new double[length];
+      double[] inputScale = new double[length];
+      string[] parts = input.ReadLine().Split();
+      for (int i = 0; i < length; i++)
+        inputStart[i] = double.Parse(parts[i]);
+      parts = input.ReadLine().Split();
+      for (int i = 0; i < length; i++)
+        inputScale[i] = double.Parse(parts[i]);
+      parts = input.ReadLine().Split();
+      double outputStart = double.Parse(parts[0]);
+      double outputScale = double.Parse(parts[1]);
+
+      TemporaryCulture.Stop();
+
+      return new RangeTransform(inputStart, inputScale, outputStart, outputScale, length);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/SVMExtensions.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/SVMExtensions.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/SVMExtensions.cs	(revision 3842)
@@ -0,0 +1,17 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SVM
+{
+    internal static class SVMExtensions
+    {
+        public static void SwapIndex<T>(this T[] list, int i, int j)
+        {
+            T tmp = list[i];
+            list[i] = list[j];
+            list[j] = tmp;
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Scaling.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Scaling.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Scaling.cs	(revision 3842)
@@ -0,0 +1,49 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+
+namespace SVM
+{
+    /// <summary>
+    /// Deals with the scaling of Problems so they have uniform ranges across all dimensions in order to
+    /// result in better SVM performance.
+    /// </summary>
+    public static class Scaling
+    {
+        /// <summary>
+        /// Scales a problem using the provided range.  This will not affect the parameter.
+        /// </summary>
+        /// <param name="prob">The problem to scale</param>
+        /// <param name="range">The Range transform to use in scaling</param>
+        /// <returns>The Scaled problem</returns>
+        public static Problem Scale(this IRangeTransform range, Problem prob)
+        {
+            Problem scaledProblem = new Problem(prob.Count, new double[prob.Count], new Node[prob.Count][], prob.MaxIndex);
+            for (int i = 0; i < scaledProblem.Count; i++)
+            {
+                scaledProblem.X[i] = new Node[prob.X[i].Length];
+                for (int j = 0; j < scaledProblem.X[i].Length; j++)
+                    scaledProblem.X[i][j] = new Node(prob.X[i][j].Index, range.Transform(prob.X[i][j].Value, prob.X[i][j].Index));
+                scaledProblem.Y[i] = prob.Y[i];
+            }
+            return scaledProblem;
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Solver.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Solver.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Solver.cs	(revision 3842)
@@ -0,0 +1,2245 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+
+namespace SVM
+{
+
+    // An SMO algorithm in Fan et al., JMLR 6(2005), p. 1889--1918
+    // Solves:
+    //
+    //	Min 0.5(\alpha^T Q \alpha) + p^T \alpha
+    //
+    //		y^T \alpha = \delta
+    //		y_i = +1 or -1
+    //		0 <= alpha_i <= Cp for y_i = 1
+    //		0 <= alpha_i <= Cn for y_i = -1
+    //
+    // Given:
+    //
+    //	Q, p, y, Cp, Cn, and an initial feasible point \alpha
+    //	l is the size of vectors and matrices
+    //	eps is the stopping tolerance
+    //
+    // solution will be put in \alpha, objective value will be put in obj
+    //
+    internal class Solver
+    {
+        protected int active_size;
+        protected sbyte[] y;
+        protected double[] G;		// gradient of objective function
+        private const byte LOWER_BOUND = 0;
+        private const byte UPPER_BOUND = 1;
+        private const byte FREE = 2;
+        private byte[] alpha_status;	// LOWER_BOUND, UPPER_BOUND, FREE
+        private double[] alpha;
+        protected IQMatrix Q;
+        protected float[] QD;
+        protected double EPS;
+        private double Cp, Cn;
+        private double[] p;
+        private int[] active_set;
+        private double[] G_bar;		// gradient, if we treat free variables as 0
+        protected int l;
+        protected bool unshrink;	// XXX
+
+        protected const double INF = double.PositiveInfinity;
+
+        private double get_C(int i)
+        {
+            return (y[i] > 0) ? Cp : Cn;
+        }
+
+        private void update_alpha_status(int i)
+        {
+            if (alpha[i] >= get_C(i))
+                alpha_status[i] = UPPER_BOUND;
+            else if (alpha[i] <= 0)
+                alpha_status[i] = LOWER_BOUND;
+            else alpha_status[i] = FREE;
+        }
+
+        protected bool is_upper_bound(int i) { return alpha_status[i] == UPPER_BOUND; }
+        protected bool is_lower_bound(int i) { return alpha_status[i] == LOWER_BOUND; }
+
+        private bool is_free(int i) { return alpha_status[i] == FREE; }
+
+        public class SolutionInfo
+        {
+            public double obj;
+            public double rho;
+            public double upper_bound_p;
+            public double upper_bound_n;
+            public double r;	// for Solver_NU
+        }
+
+        protected void swap_index(int i, int j)
+        {
+            Q.SwapIndex(i, j);
+            y.SwapIndex(i, j);
+            G.SwapIndex(i, j);
+            alpha_status.SwapIndex(i, j);
+            alpha.SwapIndex(i, j);
+            p.SwapIndex(i, j);
+            active_set.SwapIndex(i, j);
+            G_bar.SwapIndex(i, j);
+        }
+
+        protected void reconstruct_gradient()
+        {
+            // reconstruct inactive elements of G from G_bar and free variables
+
+            if (active_size == l) return;
+
+            int i, j;
+            int nr_free = 0;
+
+            for (j = active_size; j < l; j++)
+                G[j] = G_bar[j] + p[j];
+
+            for (j = 0; j < active_size; j++)
+                if (is_free(j))
+                    nr_free++;
+
+            if (2 * nr_free < active_size)
+                Procedures.info("\nWarning: using -h 0 may be faster\n");
+
+            if (nr_free * l > 2 * active_size * (l - active_size))
+            {
+                for (i = active_size; i < l; i++)
+                {
+                    float[] Q_i = Q.GetQ(i, active_size);
+                    for (j = 0; j < active_size; j++)
+                        if (is_free(j))
+                            G[i] += alpha[j] * Q_i[j];
+                }
+            }
+            else
+            {
+                for (i = 0; i < active_size; i++)
+                    if (is_free(i))
+                    {
+                        float[] Q_i = Q.GetQ(i, l);
+                        double alpha_i = alpha[i];
+                        for (j = active_size; j < l; j++)
+                            G[j] += alpha_i * Q_i[j];
+                    }
+            }
+        }
+
+        public virtual void Solve(int l, IQMatrix Q, double[] p_, sbyte[] y_, double[] alpha_, double Cp, double Cn, double eps, SolutionInfo si, bool shrinking)
+        {
+            this.l = l;
+            this.Q = Q;
+            QD = Q.GetQD();
+            p = (double[])p_.Clone();
+            y = (sbyte[])y_.Clone();
+            alpha = (double[])alpha_.Clone();
+            this.Cp = Cp;
+            this.Cn = Cn;
+            this.EPS = eps;
+            this.unshrink = false;
+
+            // initialize alpha_status
+            {
+                alpha_status = new byte[l];
+                for (int i = 0; i < l; i++)
+                    update_alpha_status(i);
+            }
+
+            // initialize active set (for shrinking)
+            {
+                active_set = new int[l];
+                for (int i = 0; i < l; i++)
+                    active_set[i] = i;
+                active_size = l;
+            }
+
+            // initialize gradient
+            {
+                G = new double[l];
+                G_bar = new double[l];
+                int i;
+                for (i = 0; i < l; i++)
+                {
+                    G[i] = p[i];
+                    G_bar[i] = 0;
+                }
+                for (i = 0; i < l; i++)
+                    if (!is_lower_bound(i))
+                    {
+                        float[] Q_i = Q.GetQ(i, l);
+                        double alpha_i = alpha[i];
+                        int j;
+                        for (j = 0; j < l; j++)
+                            G[j] += alpha_i * Q_i[j];
+                        if (is_upper_bound(i))
+                            for (j = 0; j < l; j++)
+                                G_bar[j] += get_C(i) * Q_i[j];
+                    }
+            }
+
+            // optimization step
+
+            int iter = 0;
+            int counter = Math.Min(l, 1000) + 1;
+            int[] working_set = new int[2];
+
+            while (true)
+            {
+                // show progress and do shrinking
+
+                if (--counter == 0)
+                {
+                    counter = Math.Min(l, 1000);
+                    if (shrinking) do_shrinking();
+                    Procedures.info(".");
+                }
+
+                if (select_working_set(working_set) != 0)
+                {
+                    // reconstruct the whole gradient
+                    reconstruct_gradient();
+                    // reset active set size and check
+                    active_size = l;
+                    Procedures.info("*");
+                    if (select_working_set(working_set) != 0)
+                        break;
+                    else
+                        counter = 1;	// do shrinking next iteration
+                }
+
+                int i = working_set[0];
+                int j = working_set[1];
+
+                ++iter;
+
+                // update alpha[i] and alpha[j], handle bounds carefully
+
+                float[] Q_i = Q.GetQ(i, active_size);
+                float[] Q_j = Q.GetQ(j, active_size);
+
+                double C_i = get_C(i);
+                double C_j = get_C(j);
+
+                double old_alpha_i = alpha[i];
+                double old_alpha_j = alpha[j];
+
+                if (y[i] != y[j])
+                {
+                    double quad_coef = Q_i[i] + Q_j[j] + 2 * Q_i[j];
+                    if (quad_coef <= 0)
+                        quad_coef = 1e-12;
+                    double delta = (-G[i] - G[j]) / quad_coef;
+                    double diff = alpha[i] - alpha[j];
+                    alpha[i] += delta;
+                    alpha[j] += delta;
+
+                    if (diff > 0)
+                    {
+                        if (alpha[j] < 0)
+                        {
+                            alpha[j] = 0;
+                            alpha[i] = diff;
+                        }
+                    }
+                    else
+                    {
+                        if (alpha[i] < 0)
+                        {
+                            alpha[i] = 0;
+                            alpha[j] = -diff;
+                        }
+                    }
+                    if (diff > C_i - C_j)
+                    {
+                        if (alpha[i] > C_i)
+                        {
+                            alpha[i] = C_i;
+                            alpha[j] = C_i - diff;
+                        }
+                    }
+                    else
+                    {
+                        if (alpha[j] > C_j)
+                        {
+                            alpha[j] = C_j;
+                            alpha[i] = C_j + diff;
+                        }
+                    }
+                }
+                else
+                {
+                    double quad_coef = Q_i[i] + Q_j[j] - 2 * Q_i[j];
+                    if (quad_coef <= 0)
+                        quad_coef = 1e-12;
+                    double delta = (G[i] - G[j]) / quad_coef;
+                    double sum = alpha[i] + alpha[j];
+                    alpha[i] -= delta;
+                    alpha[j] += delta;
+
+                    if (sum > C_i)
+                    {
+                        if (alpha[i] > C_i)
+                        {
+                            alpha[i] = C_i;
+                            alpha[j] = sum - C_i;
+                        }
+                    }
+                    else
+                    {
+                        if (alpha[j] < 0)
+                        {
+                            alpha[j] = 0;
+                            alpha[i] = sum;
+                        }
+                    }
+                    if (sum > C_j)
+                    {
+                        if (alpha[j] > C_j)
+                        {
+                            alpha[j] = C_j;
+                            alpha[i] = sum - C_j;
+                        }
+                    }
+                    else
+                    {
+                        if (alpha[i] < 0)
+                        {
+                            alpha[i] = 0;
+                            alpha[j] = sum;
+                        }
+                    }
+                }
+
+                // update G
+
+                double delta_alpha_i = alpha[i] - old_alpha_i;
+                double delta_alpha_j = alpha[j] - old_alpha_j;
+
+                for (int k = 0; k < active_size; k++)
+                {
+                    G[k] += Q_i[k] * delta_alpha_i + Q_j[k] * delta_alpha_j;
+                }
+
+                // update alpha_status and G_bar
+
+                {
+                    bool ui = is_upper_bound(i);
+                    bool uj = is_upper_bound(j);
+                    update_alpha_status(i);
+                    update_alpha_status(j);
+                    int k;
+                    if (ui != is_upper_bound(i))
+                    {
+                        Q_i = Q.GetQ(i, l);
+                        if (ui)
+                            for (k = 0; k < l; k++)
+                                G_bar[k] -= C_i * Q_i[k];
+                        else
+                            for (k = 0; k < l; k++)
+                                G_bar[k] += C_i * Q_i[k];
+                    }
+
+                    if (uj != is_upper_bound(j))
+                    {
+                        Q_j = Q.GetQ(j, l);
+                        if (uj)
+                            for (k = 0; k < l; k++)
+                                G_bar[k] -= C_j * Q_j[k];
+                        else
+                            for (k = 0; k < l; k++)
+                                G_bar[k] += C_j * Q_j[k];
+                    }
+                }
+
+            }
+
+            // calculate rho
+
+            si.rho = calculate_rho();
+
+            // calculate objective value
+            {
+                double v = 0;
+                int i;
+                for (i = 0; i < l; i++)
+                    v += alpha[i] * (G[i] + p[i]);
+
+                si.obj = v / 2;
+            }
+
+            // put back the solution
+            {
+                for (int i = 0; i < l; i++)
+                    alpha_[active_set[i]] = alpha[i];
+            }
+
+            si.upper_bound_p = Cp;
+            si.upper_bound_n = Cn;
+
+            Procedures.info("\noptimization finished, #iter = " + iter + "\n");
+        }
+
+        // return 1 if already optimal, return 0 otherwise
+        protected virtual int select_working_set(int[] working_set)
+        {
+            // return i,j such that
+            // i: Maximizes -y_i * grad(f)_i, i in I_up(\alpha)
+            // j: mimimizes the decrease of obj value
+            //    (if quadratic coefficeint <= 0, replace it with tau)
+            //    -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
+
+            double GMax = -INF;
+            double GMax2 = -INF;
+            int GMax_idx = -1;
+            int GMin_idx = -1;
+            double obj_diff_Min = INF;
+
+            for (int t = 0; t < active_size; t++)
+                if (y[t] == +1)
+                {
+                    if (!is_upper_bound(t))
+                        if (-G[t] >= GMax)
+                        {
+                            GMax = -G[t];
+                            GMax_idx = t;
+                        }
+                }
+                else
+                {
+                    if (!is_lower_bound(t))
+                        if (G[t] >= GMax)
+                        {
+                            GMax = G[t];
+                            GMax_idx = t;
+                        }
+                }
+
+            int i = GMax_idx;
+            float[] Q_i = null;
+            if (i != -1) // null Q_i not accessed: GMax=-INF if i=-1
+                Q_i = Q.GetQ(i, active_size);
+
+            for (int j = 0; j < active_size; j++)
+            {
+                if (y[j] == +1)
+                {
+                    if (!is_lower_bound(j))
+                    {
+                        double grad_diff = GMax + G[j];
+                        if (G[j] >= GMax2)
+                            GMax2 = G[j];
+                        if (grad_diff > 0)
+                        {
+                            double obj_diff;
+                            double quad_coef = Q_i[i] + QD[j] - 2.0 * y[i] * Q_i[j];
+                            if (quad_coef > 0)
+                                obj_diff = -(grad_diff * grad_diff) / quad_coef;
+                            else
+                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
+
+                            if (obj_diff <= obj_diff_Min)
+                            {
+                                GMin_idx = j;
+                                obj_diff_Min = obj_diff;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    if (!is_upper_bound(j))
+                    {
+                        double grad_diff = GMax - G[j];
+                        if (-G[j] >= GMax2)
+                            GMax2 = -G[j];
+                        if (grad_diff > 0)
+                        {
+                            double obj_diff;
+                            double quad_coef = Q_i[i] + QD[j] + 2.0 * y[i] * Q_i[j];
+                            if (quad_coef > 0)
+                                obj_diff = -(grad_diff * grad_diff) / quad_coef;
+                            else
+                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
+
+                            if (obj_diff <= obj_diff_Min)
+                            {
+                                GMin_idx = j;
+                                obj_diff_Min = obj_diff;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (GMax + GMax2 < EPS)
+                return 1;
+
+            working_set[0] = GMax_idx;
+            working_set[1] = GMin_idx;
+            return 0;
+        }
+
+        private bool be_shrunk(int i, double GMax1, double GMax2)
+        {
+            if (is_upper_bound(i))
+            {
+                if (y[i] == +1)
+                    return (-G[i] > GMax1);
+                else
+                    return (-G[i] > GMax2);
+            }
+            else if (is_lower_bound(i))
+            {
+                if (y[i] == +1)
+                    return (G[i] > GMax2);
+                else
+                    return (G[i] > GMax1);
+            }
+            else
+                return (false);
+        }
+
+        protected virtual void do_shrinking()
+        {
+            int i;
+            double GMax1 = -INF;		// Max { -y_i * grad(f)_i | i in I_up(\alpha) }
+            double GMax2 = -INF;		// Max { y_i * grad(f)_i | i in I_low(\alpha) }
+
+            // find Maximal violating pair first
+            for (i = 0; i < active_size; i++)
+            {
+                if (y[i] == +1)
+                {
+                    if (!is_upper_bound(i))
+                    {
+                        if (-G[i] >= GMax1)
+                            GMax1 = -G[i];
+                    }
+                    if (!is_lower_bound(i))
+                    {
+                        if (G[i] >= GMax2)
+                            GMax2 = G[i];
+                    }
+                }
+                else
+                {
+                    if (!is_upper_bound(i))
+                    {
+                        if (-G[i] >= GMax2)
+                            GMax2 = -G[i];
+                    }
+                    if (!is_lower_bound(i))
+                    {
+                        if (G[i] >= GMax1)
+                            GMax1 = G[i];
+                    }
+                }
+            }
+
+            if (unshrink == false && GMax1 + GMax2 <= EPS * 10)
+            {
+                unshrink = true;
+                reconstruct_gradient();
+                active_size = l;
+            }
+
+            for (i = 0; i < active_size; i++)
+                if (be_shrunk(i, GMax1, GMax2))
+                {
+                    active_size--;
+                    while (active_size > i)
+                    {
+                        if (!be_shrunk(active_size, GMax1, GMax2))
+                        {
+                            swap_index(i, active_size);
+                            break;
+                        }
+                        active_size--;
+                    }
+                }
+        }
+
+        protected virtual double calculate_rho()
+        {
+            double r;
+            int nr_free = 0;
+            double ub = INF, lb = -INF, sum_free = 0;
+            for (int i = 0; i < active_size; i++)
+            {
+                double yG = y[i] * G[i];
+
+                if (is_lower_bound(i))
+                {
+                    if (y[i] > 0)
+                        ub = Math.Min(ub, yG);
+                    else
+                        lb = Math.Max(lb, yG);
+                }
+                else if (is_upper_bound(i))
+                {
+                    if (y[i] < 0)
+                        ub = Math.Min(ub, yG);
+                    else
+                        lb = Math.Max(lb, yG);
+                }
+                else
+                {
+                    ++nr_free;
+                    sum_free += yG;
+                }
+            }
+
+            if (nr_free > 0)
+                r = sum_free / nr_free;
+            else
+                r = (ub + lb) / 2;
+
+            return r;
+        }
+
+    }
+
+    //
+    // Solver for nu-svm classification and regression
+    //
+    // additional constraint: e^T \alpha = constant
+    //
+    class Solver_NU : Solver
+    {
+        private SolutionInfo si;
+
+        public sealed override void Solve(int l, IQMatrix Q, double[] p, sbyte[] y,
+               double[] alpha, double Cp, double Cn, double eps,
+               SolutionInfo si, bool shrinking)
+        {
+            this.si = si;
+            base.Solve(l, Q, p, y, alpha, Cp, Cn, eps, si, shrinking);
+        }
+
+        // return 1 if already optimal, return 0 otherwise
+        protected override sealed int select_working_set(int[] working_set)
+        {
+            // return i,j such that y_i = y_j and
+            // i: Maximizes -y_i * grad(f)_i, i in I_up(\alpha)
+            // j: Minimizes the decrease of obj value
+            //    (if quadratic coefficeint <= 0, replace it with tau)
+            //    -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
+
+            double GMaxp = -INF;
+            double GMaxp2 = -INF;
+            int GMaxp_idx = -1;
+
+            double GMaxn = -INF;
+            double GMaxn2 = -INF;
+            int GMaxn_idx = -1;
+
+            int GMin_idx = -1;
+            double obj_diff_Min = INF;
+
+            for (int t = 0; t < active_size; t++)
+                if (y[t] == +1)
+                {
+                    if (!is_upper_bound(t))
+                        if (-G[t] >= GMaxp)
+                        {
+                            GMaxp = -G[t];
+                            GMaxp_idx = t;
+                        }
+                }
+                else
+                {
+                    if (!is_lower_bound(t))
+                        if (G[t] >= GMaxn)
+                        {
+                            GMaxn = G[t];
+                            GMaxn_idx = t;
+                        }
+                }
+
+            int ip = GMaxp_idx;
+            int iN = GMaxn_idx;
+            float[] Q_ip = null;
+            float[] Q_in = null;
+            if (ip != -1) // null Q_ip not accessed: GMaxp=-INF if ip=-1
+                Q_ip = Q.GetQ(ip, active_size);
+            if (iN != -1)
+                Q_in = Q.GetQ(iN, active_size);
+
+            for (int j = 0; j < active_size; j++)
+            {
+                if (y[j] == +1)
+                {
+                    if (!is_lower_bound(j))
+                    {
+                        double grad_diff = GMaxp + G[j];
+                        if (G[j] >= GMaxp2)
+                            GMaxp2 = G[j];
+                        if (grad_diff > 0)
+                        {
+                            double obj_diff;
+                            double quad_coef = Q_ip[ip] + QD[j] - 2 * Q_ip[j];
+                            if (quad_coef > 0)
+                                obj_diff = -(grad_diff * grad_diff) / quad_coef;
+                            else
+                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
+
+                            if (obj_diff <= obj_diff_Min)
+                            {
+                                GMin_idx = j;
+                                obj_diff_Min = obj_diff;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    if (!is_upper_bound(j))
+                    {
+                        double grad_diff = GMaxn - G[j];
+                        if (-G[j] >= GMaxn2)
+                            GMaxn2 = -G[j];
+                        if (grad_diff > 0)
+                        {
+                            double obj_diff;
+                            double quad_coef = Q_in[iN] + QD[j] - 2 * Q_in[j];
+                            if (quad_coef > 0)
+                                obj_diff = -(grad_diff * grad_diff) / quad_coef;
+                            else
+                                obj_diff = -(grad_diff * grad_diff) / 1e-12;
+
+                            if (obj_diff <= obj_diff_Min)
+                            {
+                                GMin_idx = j;
+                                obj_diff_Min = obj_diff;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (Math.Max(GMaxp + GMaxp2, GMaxn + GMaxn2) < EPS)
+                return 1;
+
+            if (y[GMin_idx] == +1)
+                working_set[0] = GMaxp_idx;
+            else
+                working_set[0] = GMaxn_idx;
+            working_set[1] = GMin_idx;
+
+            return 0;
+        }
+
+        private bool be_shrunk(int i, double GMax1, double GMax2, double GMax3, double GMax4)
+        {
+            if (is_upper_bound(i))
+            {
+                if (y[i] == +1)
+                    return (-G[i] > GMax1);
+                else
+                    return (-G[i] > GMax4);
+            }
+            else if (is_lower_bound(i))
+            {
+                if (y[i] == +1)
+                    return (G[i] > GMax2);
+                else
+                    return (G[i] > GMax3);
+            }
+            else
+                return (false);
+        }
+
+        protected override sealed void do_shrinking()
+        {
+            double GMax1 = -INF;	// Max { -y_i * grad(f)_i | y_i = +1, i in I_up(\alpha) }
+            double GMax2 = -INF;	// Max { y_i * grad(f)_i | y_i = +1, i in I_low(\alpha) }
+            double GMax3 = -INF;	// Max { -y_i * grad(f)_i | y_i = -1, i in I_up(\alpha) }
+            double GMax4 = -INF;	// Max { y_i * grad(f)_i | y_i = -1, i in I_low(\alpha) }
+
+            // find Maximal violating pair first
+            int i;
+            for (i = 0; i < active_size; i++)
+            {
+                if (!is_upper_bound(i))
+                {
+                    if (y[i] == +1)
+                    {
+                        if (-G[i] > GMax1) GMax1 = -G[i];
+                    }
+                    else if (-G[i] > GMax4) GMax4 = -G[i];
+                }
+                if (!is_lower_bound(i))
+                {
+                    if (y[i] == +1)
+                    {
+                        if (G[i] > GMax2) GMax2 = G[i];
+                    }
+                    else if (G[i] > GMax3) GMax3 = G[i];
+                }
+            }
+
+            if (unshrink == false && Math.Max(GMax1 + GMax2, GMax3 + GMax4) <= EPS * 10)
+            {
+                unshrink = true;
+                reconstruct_gradient();
+                active_size = l;
+            }
+
+            for (i = 0; i < active_size; i++)
+                if (be_shrunk(i, GMax1, GMax2, GMax3, GMax4))
+                {
+                    active_size--;
+                    while (active_size > i)
+                    {
+                        if (!be_shrunk(active_size, GMax1, GMax2, GMax3, GMax4))
+                        {
+                            swap_index(i, active_size);
+                            break;
+                        }
+                        active_size--;
+                    }
+                }
+        }
+
+        protected override sealed double calculate_rho()
+        {
+            int nr_free1 = 0, nr_free2 = 0;
+            double ub1 = INF, ub2 = INF;
+            double lb1 = -INF, lb2 = -INF;
+            double sum_free1 = 0, sum_free2 = 0;
+
+            for (int i = 0; i < active_size; i++)
+            {
+                if (y[i] == +1)
+                {
+                    if (is_lower_bound(i))
+                        ub1 = Math.Min(ub1, G[i]);
+                    else if (is_upper_bound(i))
+                        lb1 = Math.Max(lb1, G[i]);
+                    else
+                    {
+                        ++nr_free1;
+                        sum_free1 += G[i];
+                    }
+                }
+                else
+                {
+                    if (is_lower_bound(i))
+                        ub2 = Math.Min(ub2, G[i]);
+                    else if (is_upper_bound(i))
+                        lb2 = Math.Max(lb2, G[i]);
+                    else
+                    {
+                        ++nr_free2;
+                        sum_free2 += G[i];
+                    }
+                }
+            }
+
+            double r1, r2;
+            if (nr_free1 > 0)
+                r1 = sum_free1 / nr_free1;
+            else
+                r1 = (ub1 + lb1) / 2;
+
+            if (nr_free2 > 0)
+                r2 = sum_free2 / nr_free2;
+            else
+                r2 = (ub2 + lb2) / 2;
+
+            si.r = (r1 + r2) / 2;
+            return (r1 - r2) / 2;
+        }
+    }
+
+    //
+    // Q matrices for various formulations
+    //
+    class SVC_Q : Kernel
+    {
+        private sbyte[] y;
+        private Cache cache;
+        private float[] QD;
+
+        public SVC_Q(Problem prob, Parameter param, sbyte[] y_) : base(prob.Count, prob.X, param)
+        {
+            y = (sbyte[])y_.Clone();
+            cache = new Cache(prob.Count, (long)(param.CacheSize * (1 << 20)));
+            QD = new float[prob.Count];
+            for (int i = 0; i < prob.Count; i++)
+                QD[i] = (float)KernelFunction(i, i);
+        }
+
+        public override sealed float[] GetQ(int i, int len)
+        {
+            float[] data = null;
+            int start, j;
+            if ((start = cache.GetData(i, ref data, len)) < len)
+            {
+                for (j = start; j < len; j++)
+                    data[j] = (float)(y[i] * y[j] * KernelFunction(i, j));
+            }
+            return data;
+        }
+
+        public override sealed float[] GetQD()
+        {
+            return QD;
+        }
+
+        public override sealed void SwapIndex(int i, int j)
+        {
+            cache.SwapIndex(i, j);
+            base.SwapIndex(i, j);
+            y.SwapIndex(i, j);
+            QD.SwapIndex(i, j);
+        }
+    }
+
+    class ONE_CLASS_Q : Kernel
+    {
+        private Cache cache;
+        private float[] QD;
+
+        public ONE_CLASS_Q(Problem prob, Parameter param) :  base(prob.Count, prob.X, param)
+        {
+            cache = new Cache(prob.Count, (long)(param.CacheSize * (1 << 20)));
+            QD = new float[prob.Count];
+            for (int i = 0; i < prob.Count; i++)
+                QD[i] = (float)KernelFunction(i, i);
+        }
+
+        public override sealed float[] GetQ(int i, int len)
+        {
+            float[] data = null;
+            int start, j;
+            if ((start = cache.GetData(i, ref data, len)) < len)
+            {
+                for (j = start; j < len; j++)
+                    data[j] = (float)KernelFunction(i, j);
+            }
+            return data;
+        }
+
+        public override sealed float[] GetQD()
+        {
+            return QD;
+        }
+
+        public override sealed void SwapIndex(int i, int j)
+        {
+            cache.SwapIndex(i, j);
+            base.SwapIndex(i, j);
+            QD.SwapIndex(i, j);
+        }
+    }
+
+    class SVR_Q : Kernel
+    {
+        private int l;
+        private Cache cache;
+        private sbyte[] sign;
+        private int[] index;
+        private int next_buffer;
+        private float[][] buffer;
+        private float[] QD;
+
+        public SVR_Q(Problem prob, Parameter param) : base(prob.Count, prob.X, param)
+        {
+            l = prob.Count;
+            cache = new Cache(l, (long)(param.CacheSize * (1 << 20)));
+            QD = new float[2 * l];
+            sign = new sbyte[2 * l];
+            index = new int[2 * l];
+            for (int k = 0; k < l; k++)
+            {
+                sign[k] = 1;
+                sign[k + l] = -1;
+                index[k] = k;
+                index[k + l] = k;
+                QD[k] = (float)KernelFunction(k, k);
+                QD[k + l] = QD[k];
+            }
+            buffer = new float[2][];
+            buffer[0] = new float[2 * l];
+            buffer[1] = new float[2 * l];
+            next_buffer = 0;
+        }
+
+        public override sealed void SwapIndex(int i, int j)
+        {
+            sign.SwapIndex(i, j);
+            index.SwapIndex(i, j);
+            QD.SwapIndex(i, j);
+        }
+
+        public override sealed float[] GetQ(int i, int len)
+        {
+            float[] data = null;
+            int j, real_i = index[i];
+            if (cache.GetData(real_i, ref data, l) < l)
+            {
+                for (j = 0; j < l; j++)
+                    data[j] = (float)KernelFunction(real_i, j);
+            }
+
+            // reorder and copy
+            float[] buf = buffer[next_buffer];
+            next_buffer = 1 - next_buffer;
+            sbyte si = sign[i];
+            for (j = 0; j < len; j++)
+                buf[j] = (float)si * sign[j] * data[index[j]];
+            return buf;
+        }
+
+        public override sealed float[] GetQD()
+        {
+            return QD;
+        }
+    }
+
+    internal class Procedures
+    {
+        private static bool _verbose;
+        public static bool IsVerbose
+        {
+            get
+            {
+                return _verbose;
+            }
+            set
+            {
+                _verbose = value;
+            }
+        }
+        //
+        // construct and solve various formulations
+        //
+        public const int LIBSVM_VERSION = 289;
+
+        public static TextWriter svm_print_string = Console.Out;
+
+        public static void info(string s)
+        {
+            if(_verbose)
+                svm_print_string.Write(s);
+        }
+
+        private static void solve_c_svc(Problem prob, Parameter param,
+                        double[] alpha, Solver.SolutionInfo si,
+                        double Cp, double Cn)
+        {
+            int l = prob.Count;
+            double[] Minus_ones = new double[l];
+            sbyte[] y = new sbyte[l];
+
+            int i;
+
+            for (i = 0; i < l; i++)
+            {
+                alpha[i] = 0;
+                Minus_ones[i] = -1;
+                if (prob.Y[i] > 0) y[i] = +1; else y[i] = -1;
+            }
+
+            Solver s = new Solver();
+            s.Solve(l, new SVC_Q(prob, param, y), Minus_ones, y,
+                alpha, Cp, Cn, param.EPS, si, param.Shrinking);
+
+            double sum_alpha = 0;
+            for (i = 0; i < l; i++)
+                sum_alpha += alpha[i];
+
+            if (Cp == Cn)
+                Procedures.info("nu = " + sum_alpha / (Cp * prob.Count) + "\n");
+
+            for (i = 0; i < l; i++)
+                alpha[i] *= y[i];
+        }
+
+        private static void solve_nu_svc(Problem prob, Parameter param,
+                        double[] alpha, Solver.SolutionInfo si)
+        {
+            int i;
+            int l = prob.Count;
+            double nu = param.Nu;
+
+            sbyte[] y = new sbyte[l];
+
+            for (i = 0; i < l; i++)
+                if (prob.Y[i] > 0)
+                    y[i] = +1;
+                else
+                    y[i] = -1;
+
+            double sum_pos = nu * l / 2;
+            double sum_neg = nu * l / 2;
+
+            for (i = 0; i < l; i++)
+                if (y[i] == +1)
+                {
+                    alpha[i] = Math.Min(1.0, sum_pos);
+                    sum_pos -= alpha[i];
+                }
+                else
+                {
+                    alpha[i] = Math.Min(1.0, sum_neg);
+                    sum_neg -= alpha[i];
+                }
+
+            double[] zeros = new double[l];
+
+            for (i = 0; i < l; i++)
+                zeros[i] = 0;
+
+            Solver_NU s = new Solver_NU();
+            s.Solve(l, new SVC_Q(prob, param, y), zeros, y, alpha, 1.0, 1.0, param.EPS, si, param.Shrinking);
+            double r = si.r;
+
+            Procedures.info("C = " + 1 / r + "\n");
+
+            for (i = 0; i < l; i++)
+                alpha[i] *= y[i] / r;
+
+            si.rho /= r;
+            si.obj /= (r * r);
+            si.upper_bound_p = 1 / r;
+            si.upper_bound_n = 1 / r;
+        }
+
+        private static void solve_one_class(Problem prob, Parameter param,
+                        double[] alpha, Solver.SolutionInfo si)
+        {
+            int l = prob.Count;
+            double[] zeros = new double[l];
+            sbyte[] ones = new sbyte[l];
+            int i;
+
+            int n = (int)(param.Nu * prob.Count);	// # of alpha's at upper bound
+
+            for (i = 0; i < n; i++)
+                alpha[i] = 1;
+            if (n < prob.Count)
+                alpha[n] = param.Nu * prob.Count - n;
+            for (i = n + 1; i < l; i++)
+                alpha[i] = 0;
+
+            for (i = 0; i < l; i++)
+            {
+                zeros[i] = 0;
+                ones[i] = 1;
+            }
+
+            Solver s = new Solver();
+            s.Solve(l, new ONE_CLASS_Q(prob, param), zeros, ones, alpha, 1.0, 1.0, param.EPS, si, param.Shrinking);
+        }
+
+        private static void solve_epsilon_svr(Problem prob, Parameter param, double[] alpha, Solver.SolutionInfo si)
+        {
+            int l = prob.Count;
+            double[] alpha2 = new double[2 * l];
+            double[] linear_term = new double[2 * l];
+            sbyte[] y = new sbyte[2 * l];
+            int i;
+
+            for (i = 0; i < l; i++)
+            {
+                alpha2[i] = 0;
+                linear_term[i] = param.P - prob.Y[i];
+                y[i] = 1;
+
+                alpha2[i + l] = 0;
+                linear_term[i + l] = param.P + prob.Y[i];
+                y[i + l] = -1;
+            }
+
+            Solver s = new Solver();
+            s.Solve(2 * l, new SVR_Q(prob, param), linear_term, y, alpha2, param.C, param.C, param.EPS, si, param.Shrinking);
+
+            double sum_alpha = 0;
+            for (i = 0; i < l; i++)
+            {
+                alpha[i] = alpha2[i] - alpha2[i + l];
+                sum_alpha += Math.Abs(alpha[i]);
+            }
+            Procedures.info("nu = " + sum_alpha / (param.C * l) + "\n");
+        }
+
+        private static void solve_nu_svr(Problem prob, Parameter param,
+                        double[] alpha, Solver.SolutionInfo si)
+        {
+            int l = prob.Count;
+            double C = param.C;
+            double[] alpha2 = new double[2 * l];
+            double[] linear_term = new double[2 * l];
+            sbyte[] y = new sbyte[2 * l];
+            int i;
+
+            double sum = C * param.Nu * l / 2;
+            for (i = 0; i < l; i++)
+            {
+                alpha2[i] = alpha2[i + l] = Math.Min(sum, C);
+                sum -= alpha2[i];
+
+                linear_term[i] = -prob.Y[i];
+                y[i] = 1;
+
+                linear_term[i + l] = prob.Y[i];
+                y[i + l] = -1;
+            }
+
+            Solver_NU s = new Solver_NU();
+            s.Solve(2 * l, new SVR_Q(prob, param), linear_term, y, alpha2, C, C, param.EPS, si, param.Shrinking);
+
+            Procedures.info("epsilon = " + (-si.r) + "\n");
+
+            for (i = 0; i < l; i++)
+                alpha[i] = alpha2[i] - alpha2[i + l];
+        }
+
+        //
+        // decision_function
+        //
+        internal class decision_function
+        {
+            public double[] alpha;
+            public double rho;
+        };
+
+        static decision_function svm_train_one(Problem prob, Parameter param, double Cp, double Cn)
+        {
+            double[] alpha = new double[prob.Count];
+            Solver.SolutionInfo si = new Solver.SolutionInfo();
+            switch (param.SvmType)
+            {
+                case SvmType.C_SVC:
+                    solve_c_svc(prob, param, alpha, si, Cp, Cn);
+                    break;
+                case SvmType.NU_SVC:
+                    solve_nu_svc(prob, param, alpha, si);
+                    break;
+                case SvmType.ONE_CLASS:
+                    solve_one_class(prob, param, alpha, si);
+                    break;
+                case SvmType.EPSILON_SVR:
+                    solve_epsilon_svr(prob, param, alpha, si);
+                    break;
+                case SvmType.NU_SVR:
+                    solve_nu_svr(prob, param, alpha, si);
+                    break;
+            }
+
+            Procedures.info("obj = " + si.obj + ", rho = " + si.rho + "\n");
+
+            // output SVs
+
+            int nSV = 0;
+            int nBSV = 0;
+            for (int i = 0; i < prob.Count; i++)
+            {
+                if (Math.Abs(alpha[i]) > 0)
+                {
+                    ++nSV;
+                    if (prob.Y[i] > 0)
+                    {
+                        if (Math.Abs(alpha[i]) >= si.upper_bound_p)
+                            ++nBSV;
+                    }
+                    else
+                    {
+                        if (Math.Abs(alpha[i]) >= si.upper_bound_n)
+                            ++nBSV;
+                    }
+                }
+            }
+
+            Procedures.info("nSV = " + nSV + ", nBSV = " + nBSV + "\n");
+
+            decision_function f = new decision_function();
+            f.alpha = alpha;
+            f.rho = si.rho;
+            return f;
+        }
+
+        // Platt's binary SVM Probablistic Output: an improvement from Lin et al.
+        private static void sigmoid_train(int l, double[] dec_values, double[] labels,
+                      double[] probAB)
+        {
+            double A, B;
+            double prior1 = 0, prior0 = 0;
+            int i;
+
+            for (i = 0; i < l; i++)
+                if (labels[i] > 0) prior1 += 1;
+                else prior0 += 1;
+
+            int Max_iter = 100;	// Maximal number of iterations
+            double Min_step = 1e-10;	// Minimal step taken in line search
+            double sigma = 1e-12;	// For numerically strict PD of Hessian
+            double eps = 1e-5;
+            double hiTarget = (prior1 + 1.0) / (prior1 + 2.0);
+            double loTarget = 1 / (prior0 + 2.0);
+            double[] t = new double[l];
+            double fApB, p, q, h11, h22, h21, g1, g2, det, dA, dB, gd, stepsize;
+            double newA, newB, newf, d1, d2;
+            int iter;
+
+            // Initial Point and Initial Fun Value
+            A = 0.0; B = Math.Log((prior0 + 1.0) / (prior1 + 1.0));
+            double fval = 0.0;
+
+            for (i = 0; i < l; i++)
+            {
+                if (labels[i] > 0) t[i] = hiTarget;
+                else t[i] = loTarget;
+                fApB = dec_values[i] * A + B;
+                if (fApB >= 0)
+                    fval += t[i] * fApB + Math.Log(1 + Math.Exp(-fApB));
+                else
+                    fval += (t[i] - 1) * fApB + Math.Log(1 + Math.Exp(fApB));
+            }
+            for (iter = 0; iter < Max_iter; iter++)
+            {
+                // Update Gradient and Hessian (use H' = H + sigma I)
+                h11 = sigma; // numerically ensures strict PD
+                h22 = sigma;
+                h21 = 0.0; g1 = 0.0; g2 = 0.0;
+                for (i = 0; i < l; i++)
+                {
+                    fApB = dec_values[i] * A + B;
+                    if (fApB >= 0)
+                    {
+                        p = Math.Exp(-fApB) / (1.0 + Math.Exp(-fApB));
+                        q = 1.0 / (1.0 + Math.Exp(-fApB));
+                    }
+                    else
+                    {
+                        p = 1.0 / (1.0 + Math.Exp(fApB));
+                        q = Math.Exp(fApB) / (1.0 + Math.Exp(fApB));
+                    }
+                    d2 = p * q;
+                    h11 += dec_values[i] * dec_values[i] * d2;
+                    h22 += d2;
+                    h21 += dec_values[i] * d2;
+                    d1 = t[i] - p;
+                    g1 += dec_values[i] * d1;
+                    g2 += d1;
+                }
+
+                // Stopping Criteria
+                if (Math.Abs(g1) < eps && Math.Abs(g2) < eps)
+                    break;
+
+                // Finding Newton direction: -inv(H') * g
+                det = h11 * h22 - h21 * h21;
+                dA = -(h22 * g1 - h21 * g2) / det;
+                dB = -(-h21 * g1 + h11 * g2) / det;
+                gd = g1 * dA + g2 * dB;
+
+
+                stepsize = 1;		// Line Search
+                while (stepsize >= Min_step)
+                {
+                    newA = A + stepsize * dA;
+                    newB = B + stepsize * dB;
+
+                    // New function value
+                    newf = 0.0;
+                    for (i = 0; i < l; i++)
+                    {
+                        fApB = dec_values[i] * newA + newB;
+                        if (fApB >= 0)
+                            newf += t[i] * fApB + Math.Log(1 + Math.Exp(-fApB));
+                        else
+                            newf += (t[i] - 1) * fApB + Math.Log(1 + Math.Exp(fApB));
+                    }
+                    // Check sufficient decrease
+                    if (newf < fval + 0.0001 * stepsize * gd)
+                    {
+                        A = newA; B = newB; fval = newf;
+                        break;
+                    }
+                    else
+                        stepsize = stepsize / 2.0;
+                }
+
+                if (stepsize < Min_step)
+                {
+                    Procedures.info("Line search fails in two-class probability estimates\n");
+                    break;
+                }
+            }
+
+            if (iter >= Max_iter)
+                Procedures.info("Reaching Maximal iterations in two-class probability estimates\n");
+            probAB[0] = A; probAB[1] = B;
+        }
+
+        private static double sigmoid_predict(double decision_value, double A, double B)
+        {
+            double fApB = decision_value * A + B;
+            if (fApB >= 0)
+                return Math.Exp(-fApB) / (1.0 + Math.Exp(-fApB));
+            else
+                return 1.0 / (1 + Math.Exp(fApB));
+        }
+
+        // Method 2 from the multiclass_prob paper by Wu, Lin, and Weng
+        private static void multiclass_probability(int k, double[,] r, double[] p)
+        {
+            int t, j;
+            int iter = 0, Max_iter = Math.Max(100, k);
+            double[,] Q = new double[k,k];
+            double[] Qp = new double[k];
+            double pQp, eps = 0.005 / k;
+
+            for (t = 0; t < k; t++)
+            {
+                p[t] = 1.0 / k;  // Valid if k = 1
+                Q[t,t] = 0;
+                for (j = 0; j < t; j++)
+                {
+                    Q[t,t] += r[j,t] * r[j,t];
+                    Q[t,j] = Q[j,t];
+                }
+                for (j = t + 1; j < k; j++)
+                {
+                    Q[t,t] += r[j,t] * r[j,t];
+                    Q[t,j] = -r[j,t] * r[t,j];
+                }
+            }
+            for (iter = 0; iter < Max_iter; iter++)
+            {
+                // stopping condition, recalculate QP,pQP for numerical accuracy
+                pQp = 0;
+                for (t = 0; t < k; t++)
+                {
+                    Qp[t] = 0;
+                    for (j = 0; j < k; j++)
+                        Qp[t] += Q[t,j] * p[j];
+                    pQp += p[t] * Qp[t];
+                }
+                double Max_error = 0;
+                for (t = 0; t < k; t++)
+                {
+                    double error = Math.Abs(Qp[t] - pQp);
+                    if (error > Max_error)
+                        Max_error = error;
+                }
+                if (Max_error < eps) break;
+
+                for (t = 0; t < k; t++)
+                {
+                    double diff = (-Qp[t] + pQp) / Q[t,t];
+                    p[t] += diff;
+                    pQp = (pQp + diff * (diff * Q[t,t] + 2 * Qp[t])) / (1 + diff) / (1 + diff);
+                    for (j = 0; j < k; j++)
+                    {
+                        Qp[j] = (Qp[j] + diff * Q[t,j]) / (1 + diff);
+                        p[j] /= (1 + diff);
+                    }
+                }
+            }
+            if (iter >= Max_iter)
+                Procedures.info("Exceeds Max_iter in multiclass_prob\n");
+        }
+
+        // Cross-validation decision values for probability estimates
+        private static void svm_binary_svc_probability(Problem prob, Parameter param, double Cp, double Cn, double[] probAB)
+        {
+            int i;
+            int nr_fold = 5;
+            int[] perm = new int[prob.Count];
+            double[] dec_values = new double[prob.Count];
+
+            // random shuffle
+            Random rand = new Random();
+            for (i = 0; i < prob.Count; i++) perm[i] = i;
+            for (i = 0; i < prob.Count; i++)
+            {
+                int j = i + (int)(rand.NextDouble() * (prob.Count - i));
+                do { int _ = perm[i]; perm[i] = perm[j]; perm[j] = _; } while (false);
+            }
+            for (i = 0; i < nr_fold; i++)
+            {
+                int begin = i * prob.Count / nr_fold;
+                int end = (i + 1) * prob.Count / nr_fold;
+                int j, k;
+                Problem subprob = new Problem();
+
+                subprob.Count = prob.Count - (end - begin);
+                subprob.X = new Node[subprob.Count][];
+                subprob.Y = new double[subprob.Count];
+
+                k = 0;
+                for (j = 0; j < begin; j++)
+                {
+                    subprob.X[k] = prob.X[perm[j]];
+                    subprob.Y[k] = prob.Y[perm[j]];
+                    ++k;
+                }
+                for (j = end; j < prob.Count; j++)
+                {
+                    subprob.X[k] = prob.X[perm[j]];
+                    subprob.Y[k] = prob.Y[perm[j]];
+                    ++k;
+                }
+                int p_count = 0, n_count = 0;
+                for (j = 0; j < k; j++)
+                    if (subprob.Y[j] > 0)
+                        p_count++;
+                    else
+                        n_count++;
+
+                if (p_count == 0 && n_count == 0)
+                    for (j = begin; j < end; j++)
+                        dec_values[perm[j]] = 0;
+                else if (p_count > 0 && n_count == 0)
+                    for (j = begin; j < end; j++)
+                        dec_values[perm[j]] = 1;
+                else if (p_count == 0 && n_count > 0)
+                    for (j = begin; j < end; j++)
+                        dec_values[perm[j]] = -1;
+                else
+                {
+                    Parameter subparam = (Parameter)param.Clone();
+                    subparam.Probability = false;
+                    subparam.C = 1.0;
+                    subparam.Weights[1] = Cp;
+                    subparam.Weights[-1] = Cn;
+                    Model submodel = svm_train(subprob, subparam);
+                    for (j = begin; j < end; j++)
+                    {
+                        double[] dec_value = new double[1];
+                        svm_predict_values(submodel, prob.X[perm[j]], dec_value);
+                        dec_values[perm[j]] = dec_value[0];
+                        // ensure +1 -1 order; reason not using CV subroutine
+                        dec_values[perm[j]] *= submodel.ClassLabels[0];
+                    }
+                }
+            }
+            sigmoid_train(prob.Count, dec_values, prob.Y, probAB);
+        }
+
+        // Return parameter of a Laplace distribution 
+        private static double svm_svr_probability(Problem prob, Parameter param)
+        {
+            int i;
+            int nr_fold = 5;
+            double[] ymv = new double[prob.Count];
+            double mae = 0;
+
+            Parameter newparam = (Parameter)param.Clone();
+            newparam.Probability = false;
+            svm_cross_validation(prob, newparam, nr_fold, ymv);
+            for (i = 0; i < prob.Count; i++)
+            {
+                ymv[i] = prob.Y[i] - ymv[i];
+                mae += Math.Abs(ymv[i]);
+            }
+            mae /= prob.Count;
+            double std = Math.Sqrt(2 * mae * mae);
+            int count = 0;
+            mae = 0;
+            for (i = 0; i < prob.Count; i++)
+                if (Math.Abs(ymv[i]) > 5 * std)
+                    count = count + 1;
+                else
+                    mae += Math.Abs(ymv[i]);
+            mae /= (prob.Count - count);
+            Procedures.info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=" + mae + "\n");
+            return mae;
+        }
+
+        // label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data
+        // perm, length l, must be allocated before calling this subroutine
+        private static void svm_group_classes(Problem prob, int[] nr_class_ret, int[][] label_ret, int[][] start_ret, int[][] count_ret, int[] perm)
+        {
+            int l = prob.Count;
+            int Max_nr_class = 16;
+            int nr_class = 0;
+            int[] label = new int[Max_nr_class];
+            int[] count = new int[Max_nr_class];
+            int[] data_label = new int[l];
+            int i;
+
+            for (i = 0; i < l; i++)
+            {
+                int this_label = (int)(prob.Y[i]);
+                int j;
+                for (j = 0; j < nr_class; j++)
+                {
+                    if (this_label == label[j])
+                    {
+                        ++count[j];
+                        break;
+                    }
+                }
+                data_label[i] = j;
+                if (j == nr_class)
+                {
+                    if (nr_class == Max_nr_class)
+                    {
+                        Max_nr_class *= 2;
+                        int[] new_data = new int[Max_nr_class];
+                        Array.Copy(label, 0, new_data, 0, label.Length);
+                        label = new_data;
+                        new_data = new int[Max_nr_class];
+                        Array.Copy(count, 0, new_data, 0, count.Length);
+                        count = new_data;
+                    }
+                    label[nr_class] = this_label;
+                    count[nr_class] = 1;
+                    ++nr_class;
+                }
+            }
+
+            int[] start = new int[nr_class];
+            start[0] = 0;
+            for (i = 1; i < nr_class; i++)
+                start[i] = start[i - 1] + count[i - 1];
+            for (i = 0; i < l; i++)
+            {
+                perm[start[data_label[i]]] = i;
+                ++start[data_label[i]];
+            }
+            start[0] = 0;
+            for (i = 1; i < nr_class; i++)
+                start[i] = start[i - 1] + count[i - 1];
+
+            nr_class_ret[0] = nr_class;
+            label_ret[0] = label;
+            start_ret[0] = start;
+            count_ret[0] = count;
+        }
+
+        //
+        // Interface functions
+        //
+        public static Model svm_train(Problem prob, Parameter param)
+        {
+            Model model = new Model();
+            model.Parameter = param;
+
+            if (param.SvmType == SvmType.ONE_CLASS || 
+               param.SvmType == SvmType.EPSILON_SVR ||
+               param.SvmType == SvmType.NU_SVR)
+            {
+                // regression or one-class-svm
+                model.NumberOfClasses = 2;                
+                model.ClassLabels = null;
+                model.NumberOfSVPerClass = null;
+                model.PairwiseProbabilityA = null; model.PairwiseProbabilityB = null;
+                model.SupportVectorCoefficients = new double[1][];
+                
+                if (param.Probability &&
+                   (param.SvmType == SvmType.EPSILON_SVR ||
+                    param.SvmType == SvmType.NU_SVR))
+                {
+                    model.PairwiseProbabilityA = new double[1];
+                    model.PairwiseProbabilityA[0] = svm_svr_probability(prob, param);
+                }
+
+                decision_function f = svm_train_one(prob, param, 0, 0);
+                model.Rho = new double[1];
+                model.Rho[0] = f.rho;
+
+                int nSV = 0;
+                int i;
+                for (i = 0; i < prob.Count; i++)
+                    if (Math.Abs(f.alpha[i]) > 0) ++nSV;                
+                model.SupportVectorCount = nSV;
+                model.SupportVectors = new Node[nSV][];
+                model.SupportVectorCoefficients[0] = new double[nSV];
+                int j = 0;
+                for (i = 0; i < prob.Count; i++)
+                    if (Math.Abs(f.alpha[i]) > 0)
+                    {
+                        model.SupportVectors[j] = prob.X[i];
+                        model.SupportVectorCoefficients[0][j] = f.alpha[i];
+                        ++j;
+                    }
+            }
+            else
+            {
+                // classification
+                int l = prob.Count;
+                int[] tmp_nr_class = new int[1];
+                int[][] tmp_label = new int[1][];
+                int[][] tmp_start = new int[1][];
+                int[][] tmp_count = new int[1][];
+                int[] perm = new int[l];
+
+                // group training data of the same class
+                svm_group_classes(prob, tmp_nr_class, tmp_label, tmp_start, tmp_count, perm);
+                int nr_class = tmp_nr_class[0];
+                int[] label = tmp_label[0];
+                int[] start = tmp_start[0];
+                int[] count = tmp_count[0];
+                Node[][] x = new Node[l][];
+                int i;
+                for (i = 0; i < l; i++)
+                    x[i] = prob.X[perm[i]];
+
+                // calculate weighted C
+
+                double[] weighted_C = new double[nr_class];
+                for (i = 0; i < nr_class; i++)
+                    weighted_C[i] = param.C;
+                foreach (int weightedLabel in param.Weights.Keys)
+                {
+                    int index = Array.IndexOf<int>(label, weightedLabel);
+                    if (index < 0)
+                        Console.Error.WriteLine("warning: class label " + weightedLabel + " specified in weight is not found");
+                    else weighted_C[index] *= param.Weights[weightedLabel];
+                }
+
+                // train k*(k-1)/2 models
+
+                bool[] nonzero = new bool[l];
+                for (i = 0; i < l; i++)
+                    nonzero[i] = false;
+                decision_function[] f = new decision_function[nr_class * (nr_class - 1) / 2];
+
+                double[] probA = null, probB = null;
+                if (param.Probability)
+                {
+                    probA = new double[nr_class * (nr_class - 1) / 2];
+                    probB = new double[nr_class * (nr_class - 1) / 2];
+                }
+
+                int p = 0;
+                for (i = 0; i < nr_class; i++)
+                    for (int j = i + 1; j < nr_class; j++)
+                    {
+                        Problem sub_prob = new Problem();
+                        int si = start[i], sj = start[j];
+                        int ci = count[i], cj = count[j];
+                        sub_prob.Count = ci + cj;
+                        sub_prob.X = new Node[sub_prob.Count][];
+                        sub_prob.Y = new double[sub_prob.Count];
+                        int k;
+                        for (k = 0; k < ci; k++)
+                        {
+                            sub_prob.X[k] = x[si + k];
+                            sub_prob.Y[k] = +1;
+                        }
+                        for (k = 0; k < cj; k++)
+                        {
+                            sub_prob.X[ci + k] = x[sj + k];
+                            sub_prob.Y[ci + k] = -1;
+                        }
+
+                        if (param.Probability)
+                        {
+                            double[] probAB = new double[2];
+                            svm_binary_svc_probability(sub_prob, param, weighted_C[i], weighted_C[j], probAB);
+                            probA[p] = probAB[0];
+                            probB[p] = probAB[1];
+                        }
+
+                        f[p] = svm_train_one(sub_prob, param, weighted_C[i], weighted_C[j]);
+                        for (k = 0; k < ci; k++)
+                            if (!nonzero[si + k] && Math.Abs(f[p].alpha[k]) > 0)
+                                nonzero[si + k] = true;
+                        for (k = 0; k < cj; k++)
+                            if (!nonzero[sj + k] && Math.Abs(f[p].alpha[ci + k]) > 0)
+                                nonzero[sj + k] = true;
+                        ++p;
+                    }
+
+                // build output
+
+                model.NumberOfClasses = nr_class;
+
+                model.ClassLabels = new int[nr_class];
+                for (i = 0; i < nr_class; i++)
+                    model.ClassLabels[i] = label[i];
+
+                model.Rho = new double[nr_class * (nr_class - 1) / 2];
+                for (i = 0; i < nr_class * (nr_class - 1) / 2; i++)
+                    model.Rho[i] = f[i].rho;
+
+                if (param.Probability)
+                {
+                    model.PairwiseProbabilityA = new double[nr_class * (nr_class - 1) / 2];
+                    model.PairwiseProbabilityB = new double[nr_class * (nr_class - 1) / 2];
+                    for (i = 0; i < nr_class * (nr_class - 1) / 2; i++)
+                    {
+                        model.PairwiseProbabilityA[i] = probA[i];
+                        model.PairwiseProbabilityB[i] = probB[i];
+                    }
+                }
+                else
+                {
+                    model.PairwiseProbabilityA = null;
+                    model.PairwiseProbabilityB = null;
+                }
+
+                int nnz = 0;
+                int[] nz_count = new int[nr_class];
+                model.NumberOfSVPerClass = new int[nr_class];
+                for (i = 0; i < nr_class; i++)
+                {
+                    int nSV = 0;
+                    for (int j = 0; j < count[i]; j++)
+                        if (nonzero[start[i] + j])
+                        {
+                            ++nSV;
+                            ++nnz;
+                        }
+                    model.NumberOfSVPerClass[i] = nSV;
+                    nz_count[i] = nSV;
+                }
+
+                Procedures.info("Total nSV = " + nnz + "\n");
+
+                model.SupportVectorCount = nnz;
+                model.SupportVectors = new Node[nnz][];
+                p = 0;
+                for (i = 0; i < l; i++)
+                    if (nonzero[i]) model.SupportVectors[p++] = x[i];
+
+                int[] nz_start = new int[nr_class];
+                nz_start[0] = 0;
+                for (i = 1; i < nr_class; i++)
+                    nz_start[i] = nz_start[i - 1] + nz_count[i - 1];
+
+                model.SupportVectorCoefficients = new double[nr_class - 1][];
+                for (i = 0; i < nr_class - 1; i++)
+                    model.SupportVectorCoefficients[i] = new double[nnz];
+
+                p = 0;
+                for (i = 0; i < nr_class; i++)
+                    for (int j = i + 1; j < nr_class; j++)
+                    {
+                        // classifier (i,j): coefficients with
+                        // i are in sv_coef[j-1][nz_start[i]...],
+                        // j are in sv_coef[i][nz_start[j]...]
+
+                        int si = start[i];
+                        int sj = start[j];
+                        int ci = count[i];
+                        int cj = count[j];
+
+                        int q = nz_start[i];
+                        int k;
+                        for (k = 0; k < ci; k++)
+                            if (nonzero[si + k])
+                                model.SupportVectorCoefficients[j - 1][q++] = f[p].alpha[k];
+                        q = nz_start[j];
+                        for (k = 0; k < cj; k++)
+                            if (nonzero[sj + k])
+                                model.SupportVectorCoefficients[i][q++] = f[p].alpha[ci + k];
+                        ++p;
+                    }
+            }
+            return model;
+        }
+
+        // Stratified cross validation
+        public static void svm_cross_validation(Problem prob, Parameter param, int nr_fold, double[] target)
+        {
+            Random rand = new Random();
+            int i;
+            int[] fold_start = new int[nr_fold + 1];
+            int l = prob.Count;
+            int[] perm = new int[l];
+
+            // stratified cv may not give leave-one-out rate
+            // Each class to l folds -> some folds may have zero elements
+            if ((param.SvmType == SvmType.C_SVC ||
+                param.SvmType == SvmType.NU_SVC) && nr_fold < l)
+            {
+                int[] tmp_nr_class = new int[1];
+                int[][] tmp_label = new int[1][];
+                int[][] tmp_start = new int[1][];
+                int[][] tmp_count = new int[1][];
+
+                svm_group_classes(prob, tmp_nr_class, tmp_label, tmp_start, tmp_count, perm);
+
+                int nr_class = tmp_nr_class[0];
+                int[] label = tmp_label[0];
+                int[] start = tmp_start[0];
+                int[] count = tmp_count[0];
+
+                // random shuffle and then data grouped by fold using the array perm
+                int[] fold_count = new int[nr_fold];
+                int c;
+                int[] index = new int[l];
+                for (i = 0; i < l; i++)
+                    index[i] = perm[i];
+                for (c = 0; c < nr_class; c++)
+                    for (i = 0; i < count[c]; i++)
+                    {
+                        int j = i + (int)(rand.NextDouble() * (count[c] - i));
+                        do { int _ = index[start[c] + j]; index[start[c] + j] = index[start[c] + i]; index[start[c] + i] = _; } while (false);
+                    }
+                for (i = 0; i < nr_fold; i++)
+                {
+                    fold_count[i] = 0;
+                    for (c = 0; c < nr_class; c++)
+                        fold_count[i] += (i + 1) * count[c] / nr_fold - i * count[c] / nr_fold;
+                }
+                fold_start[0] = 0;
+                for (i = 1; i <= nr_fold; i++)
+                    fold_start[i] = fold_start[i - 1] + fold_count[i - 1];
+                for (c = 0; c < nr_class; c++)
+                    for (i = 0; i < nr_fold; i++)
+                    {
+                        int begin = start[c] + i * count[c] / nr_fold;
+                        int end = start[c] + (i + 1) * count[c] / nr_fold;
+                        for (int j = begin; j < end; j++)
+                        {
+                            perm[fold_start[i]] = index[j];
+                            fold_start[i]++;
+                        }
+                    }
+                fold_start[0] = 0;
+                for (i = 1; i <= nr_fold; i++)
+                    fold_start[i] = fold_start[i - 1] + fold_count[i - 1];
+            }
+            else
+            {
+                for (i = 0; i < l; i++) perm[i] = i;
+                for (i = 0; i < l; i++)
+                {
+                    int j = i + (int)(rand.NextDouble() * (l - i));
+                    do { int _ = perm[i]; perm[i] = perm[j]; perm[j] = _; } while (false);
+                }
+                for (i = 0; i <= nr_fold; i++)
+                    fold_start[i] = i * l / nr_fold;
+            }
+
+            for (i = 0; i < nr_fold; i++)
+            {
+                int begin = fold_start[i];
+                int end = fold_start[i + 1];
+                int j, k;
+                Problem subprob = new Problem();
+
+                subprob.Count = l - (end - begin);
+                subprob.X = new Node[subprob.Count][];
+                subprob.Y = new double[subprob.Count];
+
+                k = 0;
+                for (j = 0; j < begin; j++)
+                {
+                    subprob.X[k] = prob.X[perm[j]];
+                    subprob.Y[k] = prob.Y[perm[j]];
+                    ++k;
+                }
+                for (j = end; j < l; j++)
+                {
+                    subprob.X[k] = prob.X[perm[j]];
+                    subprob.Y[k] = prob.Y[perm[j]];
+                    ++k;
+                }
+                Model submodel = svm_train(subprob, param);
+                if (param.Probability &&
+                   (param.SvmType == SvmType.C_SVC ||
+                    param.SvmType == SvmType.NU_SVC))
+                {
+                    double[] prob_estimates = new double[svm_get_nr_class(submodel)];
+                    for (j = begin; j < end; j++)
+                        target[perm[j]] = svm_predict_probability(submodel, prob.X[perm[j]], prob_estimates);
+                }
+                else
+                    for (j = begin; j < end; j++)
+                        target[perm[j]] = svm_predict(submodel, prob.X[perm[j]]);
+            }
+        }
+
+        public static SvmType svm_get_svm_type(Model model)
+        {
+            return model.Parameter.SvmType;
+        }
+
+        public static int svm_get_nr_class(Model model)
+        {
+            return model.NumberOfClasses;
+        }
+
+        public static void svm_get_labels(Model model, int[] label)
+        {
+            if (model.ClassLabels != null)
+                for (int i = 0; i < model.NumberOfClasses; i++)
+                    label[i] = model.ClassLabels[i];
+        }
+
+        public static double svm_get_svr_probability(Model model)
+        {
+            if ((model.Parameter.SvmType == SvmType.EPSILON_SVR || model.Parameter.SvmType == SvmType.NU_SVR) &&
+                model.PairwiseProbabilityA != null)
+                return model.PairwiseProbabilityA[0];
+            else
+            {
+                Console.Error.WriteLine("Model doesn't contain information for SVR probability inference");
+                return 0;
+            }
+        }
+
+        public static void svm_predict_values(Model model, Node[] x, double[] dec_values)
+        {
+            if (model.Parameter.SvmType == SvmType.ONE_CLASS ||
+               model.Parameter.SvmType == SvmType.EPSILON_SVR ||
+               model.Parameter.SvmType == SvmType.NU_SVR)
+            {
+                double[] sv_coef = model.SupportVectorCoefficients[0];
+                double sum = 0;
+                for (int i = 0; i < model.SupportVectorCount; i++)
+                    sum += sv_coef[i] * Kernel.KernelFunction(x, model.SupportVectors[i], model.Parameter);
+                sum -= model.Rho[0];
+                dec_values[0] = sum;
+            }
+            else
+            {
+                int i;
+                int nr_class = model.NumberOfClasses;
+                int l = model.SupportVectorCount;
+
+                double[] kvalue = new double[l];
+                for (i = 0; i < l; i++)
+                    kvalue[i] = Kernel.KernelFunction(x, model.SupportVectors[i], model.Parameter);
+
+                int[] start = new int[nr_class];
+                start[0] = 0;
+                for (i = 1; i < nr_class; i++)
+                    start[i] = start[i - 1] + model.NumberOfSVPerClass[i - 1];
+
+                int p = 0;
+                for (i = 0; i < nr_class; i++)
+                    for (int j = i + 1; j < nr_class; j++)
+                    {
+                        double sum = 0;
+                        int si = start[i];
+                        int sj = start[j];
+                        int ci = model.NumberOfSVPerClass[i];
+                        int cj = model.NumberOfSVPerClass[j];
+
+                        int k;
+                        double[] coef1 = model.SupportVectorCoefficients[j - 1];
+                        double[] coef2 = model.SupportVectorCoefficients[i];
+                        for (k = 0; k < ci; k++)
+                            sum += coef1[si + k] * kvalue[si + k];
+                        for (k = 0; k < cj; k++)
+                            sum += coef2[sj + k] * kvalue[sj + k];
+                        sum -= model.Rho[p];
+                        dec_values[p] = sum;
+                        p++;
+                    }
+            }
+        }
+
+        public static double svm_predict(Model model, Node[] x)
+        {
+            if (model.Parameter.SvmType == SvmType.ONE_CLASS ||
+               model.Parameter.SvmType == SvmType.EPSILON_SVR ||
+               model.Parameter.SvmType == SvmType.NU_SVR)
+            {
+                double[] res = new double[1];
+                svm_predict_values(model, x, res);
+
+                if (model.Parameter.SvmType == SvmType.ONE_CLASS)
+                    return (res[0] > 0) ? 1 : -1;
+                else
+                    return res[0];
+            }
+            else
+            {
+                int i;
+                int nr_class = model.NumberOfClasses;
+                double[] dec_values = new double[nr_class * (nr_class - 1) / 2];
+                svm_predict_values(model, x, dec_values);
+
+                int[] vote = new int[nr_class];
+                for (i = 0; i < nr_class; i++)
+                    vote[i] = 0;
+                int pos = 0;
+                for (i = 0; i < nr_class; i++)
+                    for (int j = i + 1; j < nr_class; j++)
+                    {
+                        if (dec_values[pos++] > 0)
+                            ++vote[i];
+                        else
+                            ++vote[j];
+                    }
+
+                int vote_Max_idx = 0;
+                for (i = 1; i < nr_class; i++)
+                    if (vote[i] > vote[vote_Max_idx])
+                        vote_Max_idx = i;
+                return model.ClassLabels[vote_Max_idx];
+            }
+        }
+
+        public static double svm_predict_probability(Model model, Node[] x, double[] prob_estimates)
+        {
+            if ((model.Parameter.SvmType == SvmType.C_SVC || model.Parameter.SvmType == SvmType.NU_SVC) &&
+                model.PairwiseProbabilityA != null && model.PairwiseProbabilityB != null)
+            {
+                int i;
+                int nr_class = model.NumberOfClasses;
+                double[] dec_values = new double[nr_class * (nr_class - 1) / 2];
+                svm_predict_values(model, x, dec_values);
+
+                double Min_prob = 1e-7;
+                double[,] pairwise_prob = new double[nr_class, nr_class];
+
+                int k = 0;
+                for (i = 0; i < nr_class; i++)
+                {
+                    for (int j = i + 1; j < nr_class; j++)
+                    {
+                        pairwise_prob[i, j] = Math.Min(Math.Max(sigmoid_predict(dec_values[k], model.PairwiseProbabilityA[k], model.PairwiseProbabilityB[k]), Min_prob), 1 - Min_prob);
+                        pairwise_prob[j, i] = 1 - pairwise_prob[i, j];
+                        k++;
+                    }
+                }
+                multiclass_probability(nr_class, pairwise_prob, prob_estimates);
+
+                int prob_Max_idx = 0;
+                for (i = 1; i < nr_class; i++)
+                    if (prob_estimates[i] > prob_estimates[prob_Max_idx])
+                        prob_Max_idx = i;
+                return model.ClassLabels[prob_Max_idx];
+            }
+            else
+                return svm_predict(model, x);
+        }
+
+        public static string svm_check_parameter(Problem prob, Parameter param)
+        {
+            // svm_type
+
+            SvmType svm_type = param.SvmType;
+
+            // kernel_type, degree
+
+            KernelType kernel_type = param.KernelType;
+
+            if (param.Degree < 0)
+                return "degree of polynomial kernel < 0";
+
+            // cache_size,eps,C,nu,p,shrinking
+
+            if (param.CacheSize <= 0)
+                return "cache_size <= 0";
+
+            if (param.EPS <= 0)
+                return "eps <= 0";
+
+            if (param.Gamma == 0)
+                param.Gamma = 1.0 / prob.MaxIndex;
+
+            if (svm_type == SvmType.C_SVC ||
+               svm_type == SvmType.EPSILON_SVR ||
+               svm_type == SvmType.NU_SVR)
+                if (param.C <= 0)
+                    return "C <= 0";
+
+            if (svm_type == SvmType.NU_SVC ||
+               svm_type == SvmType.ONE_CLASS ||
+               svm_type == SvmType.NU_SVR)
+                if (param.Nu <= 0 || param.Nu > 1)
+                    return "nu <= 0 or nu > 1";
+
+            if (svm_type == SvmType.EPSILON_SVR)
+                if (param.P < 0)
+                    return "p < 0";
+
+            if (param.Probability &&
+               svm_type == SvmType.ONE_CLASS)
+                return "one-class SVM probability output not supported yet";
+
+            // check whether nu-svc is feasible
+
+            if (svm_type == SvmType.NU_SVC)
+            {
+                int l = prob.Count;
+                int Max_nr_class = 16;
+                int nr_class = 0;
+                int[] label = new int[Max_nr_class];
+                int[] count = new int[Max_nr_class];
+
+                int i;
+                for (i = 0; i < l; i++)
+                {
+                    int this_label = (int)prob.Y[i];
+                    int j;
+                    for (j = 0; j < nr_class; j++)
+                        if (this_label == label[j])
+                        {
+                            ++count[j];
+                            break;
+                        }
+
+                    if (j == nr_class)
+                    {
+                        if (nr_class == Max_nr_class)
+                        {
+                            Max_nr_class *= 2;
+                            int[] new_data = new int[Max_nr_class];
+                            Array.Copy(label, 0, new_data, 0, label.Length);
+                            label = new_data;
+
+                            new_data = new int[Max_nr_class];
+                            Array.Copy(count, 0, new_data, 0, count.Length);
+                            count = new_data;
+                        }
+                        label[nr_class] = this_label;
+                        count[nr_class] = 1;
+                        ++nr_class;
+                    }
+                }
+
+                for (i = 0; i < nr_class; i++)
+                {
+                    int n1 = count[i];
+                    for (int j = i + 1; j < nr_class; j++)
+                    {
+                        int n2 = count[j];
+                        if (param.Nu * (n1 + n2) / 2 > Math.Min(n1, n2))
+                            return "specified nu is infeasible";
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        public static int svm_check_probability_model(Model model)
+        {
+            if (((model.Parameter.SvmType == SvmType.C_SVC || model.Parameter.SvmType == SvmType.NU_SVC) &&
+            model.PairwiseProbabilityA != null && model.PairwiseProbabilityB != null) ||
+            ((model.Parameter.SvmType == SvmType.EPSILON_SVR || model.Parameter.SvmType == SvmType.NU_SVR) &&
+             model.PairwiseProbabilityA != null))
+                return 1;
+            else
+                return 0;
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/TemporaryCulture.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/TemporaryCulture.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/TemporaryCulture.cs	(revision 3842)
@@ -0,0 +1,25 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+using System.Threading;
+
+namespace SVM
+{
+    internal static class TemporaryCulture
+    {
+        private static CultureInfo _culture;
+
+        public static void Start()
+        {
+            _culture = Thread.CurrentThread.CurrentCulture;
+            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
+        }
+
+        public static void Stop()
+        {
+            Thread.CurrentThread.CurrentCulture = _culture;
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Training.cs
===================================================================
--- /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Training.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.LibSVM/1.6.3/LibSVM-1.6.3/Training.cs	(revision 3842)
@@ -0,0 +1,226 @@
+/*
+ * SVM.NET Library
+ * Copyright (C) 2008 Matthew Johnson
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using System;
+using System.Collections.Generic;
+
+namespace SVM
+{
+    /// <summary>
+    /// Class containing the routines to train SVM models.
+    /// </summary>
+    public static class Training
+    {
+        /// <summary>
+        /// Whether the system will output information to the console during the training process.
+        /// </summary>
+        public static bool IsVerbose
+        {
+            get
+            {
+                return Procedures.IsVerbose;
+            }
+            set
+            {
+                Procedures.IsVerbose = value;
+            }
+        }
+
+        private static double doCrossValidation(Problem problem, Parameter parameters, int nr_fold)
+        {
+            int i;
+            double[] target = new double[problem.Count];
+            Procedures.svm_cross_validation(problem, parameters, nr_fold, target);
+            int total_correct = 0;
+            double total_error = 0;
+            double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
+            if (parameters.SvmType == SvmType.EPSILON_SVR || parameters.SvmType == SvmType.NU_SVR)
+            {
+                for (i = 0; i < problem.Count; i++)
+                {
+                    double y = problem.Y[i];
+                    double v = target[i];
+                    total_error += (v - y) * (v - y);
+                    sumv += v;
+                    sumy += y;
+                    sumvv += v * v;
+                    sumyy += y * y;
+                    sumvy += v * y;
+                }
+                return(problem.Count * sumvy - sumv * sumy) / (Math.Sqrt(problem.Count * sumvv - sumv * sumv) * Math.Sqrt(problem.Count * sumyy - sumy * sumy));
+            }
+            else
+                for (i = 0; i < problem.Count; i++)
+                    if (target[i] == problem.Y[i])
+                        ++total_correct;
+            return (double)total_correct / problem.Count;
+        }
+        /// <summary>
+        /// Legacy.  Allows use as if this was svm_train.  See libsvm documentation for details on which arguments to pass.
+        /// </summary>
+        /// <param name="args"></param>
+        [Obsolete("Provided only for legacy compatibility, use the other Train() methods")]
+        public static void Train(params string[] args)
+        {
+            Parameter parameters;
+            Problem problem;
+            bool crossValidation;
+            int nrfold;
+            string modelFilename;
+            parseCommandLine(args, out parameters, out problem, out crossValidation, out nrfold, out modelFilename);
+            if (crossValidation)
+                PerformCrossValidation(problem, parameters, nrfold);
+            else Model.Write(modelFilename, Train(problem, parameters));
+        }
+
+        /// <summary>
+        /// Performs cross validation.
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="parameters">The parameters to test</param>
+        /// <param name="nrfold">The number of cross validations to use</param>
+        /// <returns>The cross validation score</returns>
+        public static double PerformCrossValidation(Problem problem, Parameter parameters, int nrfold)
+        {
+            string error = Procedures.svm_check_parameter(problem, parameters);
+            if (error == null)
+                return doCrossValidation(problem, parameters, nrfold);
+            else throw new Exception(error);
+        }
+
+        /// <summary>
+        /// Trains a model using the provided training data and parameters.
+        /// </summary>
+        /// <param name="problem">The training data</param>
+        /// <param name="parameters">The parameters to use</param>
+        /// <returns>A trained SVM Model</returns>
+        public static Model Train(Problem problem, Parameter parameters)
+        {
+            string error = Procedures.svm_check_parameter(problem, parameters);
+
+            if (error == null)
+                return Procedures.svm_train(problem, parameters);
+            else throw new Exception(error);
+        }
+
+        private static void parseCommandLine(string[] args, out Parameter parameters, out Problem problem, out bool crossValidation, out int nrfold, out string modelFilename)
+        {
+            int i;
+
+            parameters = new Parameter();
+            // default values
+
+            crossValidation = false;
+            nrfold = 0;
+
+            // parse options
+            for (i = 0; i < args.Length; i++)
+            {
+                if (args[i][0] != '-')
+                    break;
+                ++i;
+                switch (args[i - 1][1])
+                {
+
+                    case 's':
+                        parameters.SvmType = (SvmType)int.Parse(args[i]);
+                        break;
+
+                    case 't':
+                        parameters.KernelType = (KernelType)int.Parse(args[i]);
+                        break;
+
+                    case 'd':
+                        parameters.Degree = int.Parse(args[i]);
+                        break;
+
+                    case 'g':
+                        parameters.Gamma = double.Parse(args[i]);
+                        break;
+
+                    case 'r':
+                        parameters.Coefficient0 = double.Parse(args[i]);
+                        break;
+
+                    case 'n':
+                        parameters.Nu = double.Parse(args[i]);
+                        break;
+
+                    case 'm':
+                        parameters.CacheSize = double.Parse(args[i]);
+                        break;
+
+                    case 'c':
+                        parameters.C = double.Parse(args[i]);
+                        break;
+
+                    case 'e':
+                        parameters.EPS = double.Parse(args[i]);
+                        break;
+
+                    case 'p':
+                        parameters.P = double.Parse(args[i]);
+                        break;
+
+                    case 'h':
+                        parameters.Shrinking = int.Parse(args[i]) == 1;
+                        break;
+
+                    case 'b':
+                        parameters.Probability = int.Parse(args[i]) == 1;
+                        break;
+
+                    case 'v':
+                        crossValidation = true;
+                        nrfold = int.Parse(args[i]);
+                        if (nrfold < 2)
+                        {
+                            throw new ArgumentException("n-fold cross validation: n must >= 2");
+                        }
+                        break;
+
+                    case 'w':
+                        parameters.Weights[int.Parse(args[i - 1].Substring(2))] = double.Parse(args[1]);
+                        break;
+
+                    default:
+                        throw new ArgumentException("Unknown Parameter");
+                }
+            }
+
+            // determine filenames
+
+            if (i >= args.Length)
+                throw new ArgumentException("No input file specified");
+
+            problem = Problem.Read(args[i]);
+
+            if (parameters.Gamma == 0)
+                parameters.Gamma = 1.0 / problem.MaxIndex;
+
+            if (i < args.Length - 1)
+                modelFilename = args[i + 1];
+            else
+            {
+                int p = args[i].LastIndexOf('/') + 1;
+                modelFilename = args[i].Substring(p) + ".model";
+            }
+        }
+    }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj	(revision 3841)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLab.Problems.DataAnalysis.Regression-3.3.csproj	(revision 3842)
@@ -87,4 +87,6 @@
     <Compile Include="LinearRegression\LinearRegressionSolutionCreator.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="SupportVectorRegression\BestSupportVectorRegressionSolutionAnalyzer.cs" />
+    <Compile Include="SupportVectorRegression\SupportVectorRegressionSolution.cs" />
     <Compile Include="Symbolic\Analyzers\BestSymbolicRegressionSolutionAnalyzer.cs" />
     <Compile Include="Symbolic\Analyzers\ISymbolicRegressionAnalyzer.cs" />
@@ -149,4 +151,12 @@
       <Project>{01BBCB5A-144A-4A7E-908E-079849E2F7CF}</Project>
       <Name>HeuristicLab.ALGLIB-2.5.0</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\HeuristicLab.LibSVM-1.6.3\HeuristicLab.LibSVM-1.6.3.csproj">
+      <Project>{89B50302-9CEE-4D13-9779-633EADCAE624}</Project>
+      <Name>HeuristicLab.LibSVM-1.6.3 %28HeuristicLab.ExtLibs\HeuristicLab.LibSVM\HeuristicLab.LibSVM-1.6.3\HeuristicLab.LibSVM-1.6.3%29</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\LibSVM-1.6.3\LibSVM-1.6.3.csproj">
+      <Project>{A16F23B5-FB62-499E-A831-26953AA56FE2}</Project>
+      <Name>LibSVM-1.6.3</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLabProblemsDataAnalysisRegressionPlugin.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLabProblemsDataAnalysisRegressionPlugin.cs.frame	(revision 3841)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/HeuristicLabProblemsDataAnalysisRegressionPlugin.cs.frame	(revision 3842)
@@ -28,4 +28,5 @@
   [Plugin("HeuristicLab.Problems.DataAnalysis.Regression","3.3.0.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.DataAnalysis.Regression-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "2.5.0.0")]
   [PluginDependency("HeuristicLab.Analysis", "3.3.0.0")]
   [PluginDependency("HeuristicLab.Collections", "3.3.0.0")]
@@ -35,4 +36,5 @@
   [PluginDependency("HeuristicLab.Data", "3.3.0.0")]
   [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding","3.3.0.0")]
+  [PluginDependency("HeuristicLab.LibSVM", "1.6.3.0")]
   [PluginDependency("HeuristicLab.Operators", "3.3.0.0")]
   [PluginDependency("HeuristicLab.Optimization", "3.3.0.0")]
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/SupportVectorRegression/BestSupportVectorRegressionSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/SupportVectorRegression/BestSupportVectorRegressionSolutionAnalyzer.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/SupportVectorRegression/BestSupportVectorRegressionSolutionAnalyzer.cs	(revision 3842)
@@ -0,0 +1,177 @@
+#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using System.Collections.Generic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Evaluators;
+using HeuristicLab.Problems.DataAnalysis.SupportVectorMachine;
+
+namespace HeuristicLab.Problems.DataAnalysis.Regression.SupportVectorRegression {
+  [Item("BestSupportVectorRegressionSolutionAnalyzer", "An operator for analyzing the best support vector solution of regression problems.")]
+  [StorableClass]
+  public sealed class BestSymbolicRegressionSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer {
+    private const string SupportVectorRegressionModelParameterName = "SupportVectorRegressionModel";
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string QualityParameterName = "Quality";
+    private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
+    private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
+    private const string BestSolutionParameterName = "BestSolution";
+    private const string BestSolutionQualityParameterName = "BestSolutionQuality";
+    private const string ResultsParameterName = "Results";
+    private const string BestSolutionResultName = "Best solution (on validiation set)";
+    private const string BestSolutionInputvariableCountResultName = "Variables used by best solution";
+    private const string BestSolutionTrainingRSquared = "Best solution R² (training)";
+    private const string BestSolutionTestRSquared = "Best solution R² (test)";
+    private const string BestSolutionTrainingMse = "Best solution mean squared error (training)";
+    private const string BestSolutionTestMse = "Best solution mean squared error (test)";
+    private const string BestSolutionTrainingRelativeError = "Best solution average relative error (training)";
+    private const string BestSolutionTestRelativeError = "Best solution average relative error (test)";
+
+    public ScopeTreeLookupParameter<SupportVectorMachineModel> SupportVectorRegressionModelParameter {
+      get { return (ScopeTreeLookupParameter<SupportVectorMachineModel>)Parameters[SupportVectorRegressionModelParameterName]; }
+    }
+    public IValueLookupParameter<DataAnalysisProblemData> ProblemDataParameter {
+      get { return (IValueLookupParameter<DataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> UpperEstimationLimitParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[UpperEstimationLimitParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> LowerEstimationLimitParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[LowerEstimationLimitParameterName]; }
+    }
+    public ILookupParameter<SupportVectorRegressionSolution> BestSolutionParameter {
+      get { return (ILookupParameter<SupportVectorRegressionSolution>)Parameters[BestSolutionParameterName]; }
+    }
+    public ILookupParameter<DoubleValue> BestSolutionQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[BestSolutionQualityParameterName]; }
+    }
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
+    }
+
+    public BestSymbolicRegressionSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<SupportVectorMachineModel>(SupportVectorRegressionModelParameterName, "The support vector regression models to analyze."));
+      Parameters.Add(new ValueLookupParameter<DataAnalysisProblemData>(ProblemDataParameterName, "The problem data for which the support vector model is a solution."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(UpperEstimationLimitParameterName, "The upper estimation limit that was set for the evaluation of the support vector model."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(LowerEstimationLimitParameterName, "The lower estimation limit that was set for the evaluation of the support vector model."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>(QualityParameterName, "The qualities of the support vector models which should be analyzed."));
+      Parameters.Add(new LookupParameter<SupportVectorRegressionSolution>(BestSolutionParameterName, "The best support vector solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>(BestSolutionQualityParameterName, "The quality of the best support vector solution."));
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The result collection where the best support vector solution should be stored."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      ItemArray<SupportVectorMachineModel> models = SupportVectorRegressionModelParameter.ActualValue;
+      DataAnalysisProblemData problemData = ProblemDataParameter.ActualValue;
+      DoubleValue upperEstimationLimit = UpperEstimationLimitParameter.ActualValue;
+      DoubleValue lowerEstimationLimit = LowerEstimationLimitParameter.ActualValue;
+      var inputVariables = ProblemDataParameter.ActualValue.InputVariables.Select(x => x.Value);
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
+      SupportVectorRegressionSolution solution = BestSolutionParameter.ActualValue;
+      if (solution == null) {
+        solution = new SupportVectorRegressionSolution(problemData, models[i], inputVariables, lowerEstimationLimit.Value, upperEstimationLimit.Value);
+        BestSolutionParameter.ActualValue = solution;
+        BestSolutionQualityParameter.ActualValue = qualities[i];
+        results.Add(new Result(BestSolutionResultName, solution));
+        results.Add(new Result(BestSolutionInputvariableCountResultName, new IntValue(inputVariables.Count())));
+        #region calculate R2,MSE,Rel Error
+        double[] trainingValues = problemData.Dataset.GetVariableValues(
+          problemData.TargetVariable.Value,
+          problemData.TrainingSamplesStart.Value,
+          problemData.TrainingSamplesEnd.Value);
+        double[] testValues = problemData.Dataset.GetVariableValues(
+          problemData.TargetVariable.Value,
+          problemData.TestSamplesStart.Value,
+          problemData.TestSamplesEnd.Value);
+        double trainingR2 = SimpleRSquaredEvaluator.Calculate(trainingValues, solution.EstimatedTrainingValues);
+        double testR2 = SimpleRSquaredEvaluator.Calculate(testValues, solution.EstimatedTestValues);
+        double trainingMse = SimpleMSEEvaluator.Calculate(trainingValues, solution.EstimatedTrainingValues);
+        double testMse = SimpleMSEEvaluator.Calculate(testValues, solution.EstimatedTestValues);
+        double trainingRelError = SimpleMeanAbsolutePercentageErrorEvaluator.Calculate(trainingValues, solution.EstimatedTrainingValues);
+        double testRelError = SimpleMeanAbsolutePercentageErrorEvaluator.Calculate(testValues, solution.EstimatedTestValues);
+        results.Add(new Result(BestSolutionTrainingRSquared, new DoubleValue(trainingR2)));
+        results.Add(new Result(BestSolutionTestRSquared, new DoubleValue(testR2)));
+        results.Add(new Result(BestSolutionTrainingMse, new DoubleValue(trainingMse)));
+        results.Add(new Result(BestSolutionTestMse, new DoubleValue(testMse)));
+        results.Add(new Result(BestSolutionTrainingRelativeError, new DoubleValue(trainingRelError)));
+        results.Add(new Result(BestSolutionTestRelativeError, new DoubleValue(testRelError)));
+        #endregion
+      } else {
+        if (BestSolutionQualityParameter.ActualValue.Value > qualities[i].Value) {
+          solution = new SupportVectorRegressionSolution(problemData, models[i], inputVariables, lowerEstimationLimit.Value, upperEstimationLimit.Value);
+          BestSolutionParameter.ActualValue = solution;
+          BestSolutionQualityParameter.ActualValue = qualities[i];
+          results[BestSolutionResultName].Value = solution;
+          results[BestSolutionInputvariableCountResultName].Value = new IntValue(inputVariables.Count());
+          #region update R2,MSE, Rel Error
+          double[] trainingValues = problemData.Dataset.GetVariableValues(
+            problemData.TargetVariable.Value,
+            problemData.TrainingSamplesStart.Value,
+            problemData.TrainingSamplesEnd.Value);
+          double[] testValues = problemData.Dataset.GetVariableValues(
+            problemData.TargetVariable.Value,
+            problemData.TestSamplesStart.Value,
+            problemData.TestSamplesEnd.Value);
+          double trainingR2 = SimpleRSquaredEvaluator.Calculate(trainingValues, solution.EstimatedTrainingValues);
+          double testR2 = SimpleRSquaredEvaluator.Calculate(testValues, solution.EstimatedTestValues);
+          double trainingMse = SimpleMSEEvaluator.Calculate(trainingValues, solution.EstimatedTrainingValues);
+          double testMse = SimpleMSEEvaluator.Calculate(testValues, solution.EstimatedTestValues);
+          double trainingRelError = SimpleMeanAbsolutePercentageErrorEvaluator.Calculate(trainingValues, solution.EstimatedTrainingValues);
+          double testRelError = SimpleMeanAbsolutePercentageErrorEvaluator.Calculate(testValues, solution.EstimatedTestValues);
+          results[BestSolutionTrainingRSquared].Value = new DoubleValue(trainingR2);
+          results[BestSolutionTestRSquared].Value = new DoubleValue(testR2);
+          results[BestSolutionTrainingMse].Value = new DoubleValue(trainingMse);
+          results[BestSolutionTestMse].Value = new DoubleValue(testMse);
+          results[BestSolutionTrainingRelativeError].Value = new DoubleValue(trainingRelError);
+          results[BestSolutionTestRelativeError].Value = new DoubleValue(testRelError);
+          #endregion
+        }
+      }
+
+      return base.Apply();
+    }
+
+    private IEnumerable<string> GetInputVariables(SymbolicExpressionTree tree) {
+      return (from varNode in tree.IterateNodesPrefix().OfType<VariableTreeNode>()
+              select varNode.VariableName).Distinct();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/SupportVectorRegression/SupportVectorRegressionSolution.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/SupportVectorRegression/SupportVectorRegressionSolution.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/SupportVectorRegression/SupportVectorRegressionSolution.cs	(revision 3842)
@@ -0,0 +1,108 @@
+#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.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using System.Collections.Generic;
+using System.Linq;
+using System.Drawing;
+using HeuristicLab.Problems.DataAnalysis.SupportVectorMachine;
+using SVM;
+
+namespace HeuristicLab.Problems.DataAnalysis.Regression.SupportVectorRegression {
+  /// <summary>
+  /// Represents a support vector solution for a regression problem which can be visualized in the GUI.
+  /// </summary>
+  [Item("SupportVectorRegressionSolution", "Represents a support vector solution for a regression problem which can be visualized in the GUI.")]
+  [StorableClass]
+  public sealed class SupportVectorRegressionSolution : DataAnalysisSolution {
+    public override Image ItemImage {
+      get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Function; }
+    }
+
+    [Storable]
+    private SupportVectorMachineModel model;
+    public SupportVectorMachineModel Model {
+      get { return model; }
+    }
+
+    [Storable]
+    private List<string> inputVariables;
+
+    public SupportVectorRegressionSolution() : base() { }
+    public SupportVectorRegressionSolution(DataAnalysisProblemData problemData, SupportVectorMachineModel model, IEnumerable<string> inputVariables, double lowerEstimationLimit, double upperEstimationLimit)
+      : base(problemData, lowerEstimationLimit, upperEstimationLimit) {
+      this.model = model;
+      this.inputVariables = new List<string>(inputVariables);
+    }
+
+    protected override void OnProblemDataChanged(EventArgs e) {
+      RecalculateEstimatedValues();
+    }
+
+    private void RecalculateEstimatedValues() {
+      SVM.Problem problem = SupportVectorMachineUtil.CreateSvmProblem(ProblemData, 0, ProblemData.Dataset.Rows);
+      SVM.Problem scaledProblem = Scaling.Scale(model.RangeTransform, problem);
+
+      estimatedValues = (from row in Enumerable.Range(0, scaledProblem.Count)
+                         let prediction = SVM.Prediction.Predict(model.Model, scaledProblem.X[row])
+                         let boundedX = Math.Min(UpperEstimationLimit, Math.Max(LowerEstimationLimit, prediction))
+                         select double.IsNaN(boundedX) ? UpperEstimationLimit : boundedX).ToList();
+      OnEstimatedValuesChanged(EventArgs.Empty);
+    }
+
+    private 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();
+      }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      SupportVectorRegressionSolution clone = (SupportVectorRegressionSolution)base.Clone(cloner);
+      clone.model = (SupportVectorMachineModel)cloner.Clone(model);
+      return clone;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/HeuristicLab.Problems.DataAnalysis-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/HeuristicLab.Problems.DataAnalysis-3.3.csproj	(revision 3841)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/HeuristicLab.Problems.DataAnalysis-3.3.csproj	(revision 3842)
@@ -100,4 +100,8 @@
     <Compile Include="MatrixExtensions.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="SupportVectorMachine\SupportVectorMachineModel.cs" />
+    <Compile Include="SupportVectorMachine\SupportVectorMachineModelCreator.cs" />
+    <Compile Include="SupportVectorMachine\SupportVectorMachineModelEvaluator.cs" />
+    <Compile Include="SupportVectorMachine\SupportVectorMachineUtil.cs" />
     <Compile Include="Symbolic\ArithmeticExpressionGrammar.cs" />
     <Compile Include="Symbolic\FullFunctionalExpressionGrammar.cs" />
@@ -154,4 +158,12 @@
       <Name>HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.3</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\HeuristicLab.LibSVM-1.6.3\HeuristicLab.LibSVM-1.6.3.csproj">
+      <Project>{89B50302-9CEE-4D13-9779-633EADCAE624}</Project>
+      <Name>HeuristicLab.LibSVM-1.6.3 %28HeuristicLab.ExtLibs\HeuristicLab.LibSVM\HeuristicLab.LibSVM-1.6.3\HeuristicLab.LibSVM-1.6.3%29</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\LibSVM-1.6.3\LibSVM-1.6.3.csproj">
+      <Project>{A16F23B5-FB62-499E-A831-26953AA56FE2}</Project>
+      <Name>LibSVM-1.6.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
       <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/HeuristicLabProblemsDataAnalysisPlugin.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/HeuristicLabProblemsDataAnalysisPlugin.cs.frame	(revision 3841)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/HeuristicLabProblemsDataAnalysisPlugin.cs.frame	(revision 3842)
@@ -34,4 +34,5 @@
   [PluginDependency("HeuristicLab.Data", "3.3.0.0")]
   [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.3.0.0")]
+  [PluginDependency("HeuristicLab.LibSVM", "1.6.3.0")]
   [PluginDependency("HeuristicLab.Operators", "3.3.0.0")]
   [PluginDependency("HeuristicLab.Parameters", "3.3.0.0")]
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModel.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModel.cs	(revision 3842)
@@ -0,0 +1,139 @@
+#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.Text;
+using System.Xml;
+using HeuristicLab.Core;
+using System.Globalization;
+using System.IO;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Problems.DataAnalysis.SupportVectorMachine {
+  /// <summary>
+  /// Represents a support vector machine model.
+  /// </summary>
+  [StorableClass]
+  [Item("SupportVectorMachineModel", "Represents a support vector machine model.")]
+  public class SupportVectorMachineModel : NamedItem {
+    private SVM.Model model;
+    /// <summary>
+    /// Gets or sets the SVM model.
+    /// </summary>
+    public SVM.Model Model {
+      get { return model; }
+      set { model = value; }
+    }
+
+    /// <summary>
+    /// Gets or sets the range transformation for the model.
+    /// </summary>
+    private SVM.RangeTransform rangeTransform;
+    public SVM.RangeTransform RangeTransform {
+      get { return rangeTransform; }
+      set { rangeTransform = value; }
+    }
+
+    #region persistence
+    [Storable]
+    private string ModelAsString {
+      get {
+        using (MemoryStream stream = new MemoryStream()) {
+          SVM.Model.Write(stream, Model);
+          stream.Seek(0, System.IO.SeekOrigin.Begin);
+          StreamReader reader = new StreamReader(stream);
+          return reader.ReadToEnd();
+        }
+      }
+      set {
+        using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(value))) {
+          model = SVM.Model.Read(stream);
+        }
+      }
+    }
+    [Storable]
+    private string RangeTransformAsString {
+      get {
+        using (MemoryStream stream = new MemoryStream()) {
+          SVM.RangeTransform.Write(stream, RangeTransform);
+          stream.Seek(0, System.IO.SeekOrigin.Begin);
+          StreamReader reader = new StreamReader(stream);
+          return reader.ReadToEnd();
+        }
+      }
+      set {
+        using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(value))) {
+          RangeTransform = SVM.RangeTransform.Read(stream);
+        }
+      }
+    }
+    #endregion
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      SupportVectorMachineModel clone = (SupportVectorMachineModel)base.Clone(cloner);
+      // beware we are only using a shallow copy here! (gkronber)
+      clone.model = model;
+      clone.rangeTransform = rangeTransform;
+      return clone;
+    }
+
+    /// <summary>
+    ///  Exports the <paramref name="model"/> in string representation to output stream <paramref name="s"/>
+    /// </summary>
+    /// <param name="model">The support vector regression model to export</param>
+    /// <param name="s">The output stream to export the model to</param>
+    public static void Export(SupportVectorMachineModel model, Stream s) {
+      StreamWriter writer = new StreamWriter(s);
+      writer.WriteLine("RangeTransform:");
+      writer.Flush();
+      using (MemoryStream memStream = new MemoryStream()) {
+        SVM.RangeTransform.Write(memStream, model.RangeTransform);
+        memStream.Seek(0, SeekOrigin.Begin);
+        memStream.WriteTo(s);
+      }
+      writer.WriteLine("Model:");
+      writer.Flush();
+      using (MemoryStream memStream = new MemoryStream()) {
+        SVM.Model.Write(memStream, model.Model);
+        memStream.Seek(0, SeekOrigin.Begin);
+        memStream.WriteTo(s);
+      }
+      s.Flush();
+    }
+
+    /// <summary>
+    /// Imports a support vector machine model given as string representation.
+    /// </summary>
+    /// <param name="reader">The reader to retrieve the string representation from</param>
+    /// <returns>The imported support vector machine model.</returns>
+    public static SupportVectorMachineModel Import(TextReader reader) {
+      SupportVectorMachineModel model = new SupportVectorMachineModel();
+      while (reader.ReadLine().Trim() != "RangeTransform:") ; // read until line "RangeTransform";
+      model.RangeTransform = SVM.RangeTransform.Read(reader);
+      // read until "Model:"
+      while (reader.ReadLine().Trim() != "Model:") ;
+      model.Model = SVM.Model.Read(reader);
+      return model;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModelCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModelCreator.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModelCreator.cs	(revision 3842)
@@ -0,0 +1,165 @@
+﻿#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.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using System.Threading;
+using HeuristicLab.LibSVM;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using SVM;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.SupportVectorMachine {
+  /// <summary>
+  /// Represents an operator that creates a support vector machine model.
+  /// </summary>
+  [StorableClass]
+  [Item("SupportVectorMachineModelCreator", "Represents an operator that creates a support vector machine model.")]
+  public class SupportVectorMachineModelCreator : SingleSuccessorOperator {
+    private const string DataAnalysisProblemDataParameterName = "DataAnalysisProblemData";
+    private const string SvmTypeParameterName = "SvmType";
+    private const string KernelTypeParameterName = "KernelType";
+    private const string CostParameterName = "Cost";
+    private const string NuParameterName = "Nu";
+    private const string GammaParameterName = "Gamma";
+    private const string ModelParameterName = "SupportVectorMachineModel";
+
+    #region parameter properties
+    public IValueLookupParameter<DataAnalysisProblemData> DataAnalysisProblemDataParameter {
+      get { return (IValueLookupParameter<DataAnalysisProblemData>)Parameters[DataAnalysisProblemDataParameterName]; }
+    }
+    public IValueParameter<StringValue> SvmTypeParameter {
+      get { return (IValueParameter<StringValue>)Parameters[SvmTypeParameterName]; }
+    }
+    public IValueParameter<StringValue> KernelTypeParameter {
+      get { return (IValueParameter<StringValue>)Parameters[KernelTypeParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> NuParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[NuParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> CostParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[CostParameterName]; }
+    }
+    public IValueLookupParameter<DoubleValue> GammaParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters[GammaParameterName]; }
+    }
+    public ILookupParameter<SupportVectorMachineModel> SupportVectorMachineModelParameter {
+      get { return (ILookupParameter<SupportVectorMachineModel>)Parameters[ModelParameterName]; }
+    }
+    #endregion
+    #region properties
+    public DataAnalysisProblemData DataAnalysisProblemData {
+      get { return DataAnalysisProblemDataParameter.ActualValue; }
+    }
+    public StringValue SvmType {
+      get { return SvmTypeParameter.Value; }
+    }
+    public StringValue KernelType {
+      get { return KernelTypeParameter.Value; }
+    }
+    public DoubleValue Nu {
+      get { return NuParameter.ActualValue; }
+    }
+    public DoubleValue Cost {
+      get { return CostParameter.ActualValue; }
+    }
+    public DoubleValue Gamma {
+      get { return GammaParameter.ActualValue; }
+    }
+    #endregion
+
+    public SupportVectorMachineModelCreator()
+      : base() {
+      #region svm types
+      StringValue cSvcType = new StringValue("C_SVC").AsReadOnly();
+      StringValue nuSvcType = new StringValue("NU_SVC").AsReadOnly();
+      StringValue eSvrType = new StringValue("EPSILON_SVR").AsReadOnly();
+      StringValue nuSvrType = new StringValue("NU_SVR").AsReadOnly();
+      ItemSet<StringValue> allowedSvmTypes = new ItemSet<StringValue>();
+      allowedSvmTypes.Add(cSvcType);
+      allowedSvmTypes.Add(nuSvcType);
+      allowedSvmTypes.Add(eSvrType);
+      allowedSvmTypes.Add(nuSvrType);
+      #endregion
+      #region kernel types
+      StringValue rbfKernelType = new StringValue("RBF").AsReadOnly();
+      StringValue linearKernelType = new StringValue("LINEAR").AsReadOnly();
+      StringValue polynomialKernelType = new StringValue("POLY").AsReadOnly();
+      StringValue sigmoidKernelType = new StringValue("SIGMOID").AsReadOnly();
+      ItemSet<StringValue> allowedKernelTypes = new ItemSet<StringValue>();
+      allowedKernelTypes.Add(rbfKernelType);
+      allowedKernelTypes.Add(linearKernelType);
+      allowedKernelTypes.Add(polynomialKernelType);
+      allowedKernelTypes.Add(sigmoidKernelType);
+      #endregion
+      Parameters.Add(new ValueLookupParameter<DataAnalysisProblemData>(DataAnalysisProblemDataParameterName, "The data analysis problem data to use for training."));
+      Parameters.Add(new ConstrainedValueParameter<StringValue>(SvmTypeParameterName, "The type of SVM to use.", allowedSvmTypes, nuSvrType));
+      Parameters.Add(new ConstrainedValueParameter<StringValue>(KernelTypeParameterName, "The kernel type to use for the SVM.", allowedKernelTypes, rbfKernelType));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(NuParameterName, "The value of the nu parameter nu-SVC, one-class SVM and nu-SVR."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(CostParameterName, "The value of the C (cost) parameter of C-SVC, epsilon-SVR and nu-SVR."));
+      Parameters.Add(new ValueLookupParameter<DoubleValue>(GammaParameterName, "The value of the gamma parameter in the kernel function."));
+      Parameters.Add(new LookupParameter<SupportVectorMachineModel>(ModelParameterName, "The result model generated by the SVM."));
+    }
+
+    public override IOperation Apply() {
+
+      SupportVectorMachineModel model = TrainModel(DataAnalysisProblemData,
+                             SvmType.Value, KernelType.Value,
+                             Cost.Value, Nu.Value, Gamma.Value);
+      SupportVectorMachineModelParameter.ActualValue = model;
+
+      return base.Apply();
+    }
+
+    public static SupportVectorMachineModel TrainModel(
+      DataAnalysisProblemData problemData,
+      string svmType, string kernelType,
+      double cost, double nu, double gamma) {
+      int targetVariableIndex = problemData.Dataset.GetVariableIndex(problemData.TargetVariable.Value);
+
+      //extract SVM parameters from scope and set them
+      SVM.Parameter parameter = new SVM.Parameter();
+      parameter.SvmType = (SVM.SvmType)Enum.Parse(typeof(SVM.SvmType), svmType, true);
+      parameter.KernelType = (SVM.KernelType)Enum.Parse(typeof(SVM.KernelType), kernelType, true);
+      parameter.C = cost;
+      parameter.Nu = nu;
+      parameter.Gamma = gamma;
+      parameter.CacheSize = 500;
+      parameter.Probability = false;
+
+
+      SVM.Problem problem = SupportVectorMachineUtil.CreateSvmProblem(problemData, problemData.TrainingSamplesStart.Value, problemData.TrainingSamplesEnd.Value);
+      SVM.RangeTransform rangeTransform = SVM.RangeTransform.Compute(problem);
+      SVM.Problem scaledProblem = Scaling.Scale(rangeTransform, problem);
+      var model = new SupportVectorMachineModel();
+
+      model.Model = SVM.Training.Train(scaledProblem, parameter);
+      model.RangeTransform = rangeTransform;
+
+      return model;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModelEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModelEvaluator.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineModelEvaluator.cs	(revision 3842)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2009 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using SVM;
+using HeuristicLab.Operators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.SupportVectorMachine {
+  [StorableClass]
+  [Item("SupportVectorMachineModelEvaluator", "Represents a operator that evaluates a support vector machine model on a data set.")]
+  public class SupportVectorMachineModelEvaluator : SingleSuccessorOperator {
+    private const string DataAnalysisProblemDataParameterName = "DataAnalysisProblemData";
+    private const string ModelParameterName = "SupportVectorMachineModel";
+    private const string SamplesStartParameterName = "SamplesStart";
+    private const string SamplesEndParameterName = "SamplesEnd";
+    private const string ValuesParameterName = "Values";
+
+    #region parameter properties
+    public IValueLookupParameter<DataAnalysisProblemData> DataAnalysisProblemDataParameter {
+      get { return (IValueLookupParameter<DataAnalysisProblemData>)Parameters[DataAnalysisProblemDataParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> SamplesStartParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesStartParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> SamplesEndParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesEndParameterName]; }
+    }
+    public ILookupParameter<SupportVectorMachineModel> SupportVectorMachineModelParameter {
+      get { return (ILookupParameter<SupportVectorMachineModel>)Parameters[ModelParameterName]; }
+    }
+    public ILookupParameter<DoubleMatrix> ValuesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters[ValuesParameterName]; }
+    }
+    #endregion
+    #region properties
+    public DataAnalysisProblemData DataAnalysisProblemData {
+      get { return DataAnalysisProblemDataParameter.ActualValue; }
+    }
+    public SupportVectorMachineModel SupportVectorMachineModel {
+      get { return SupportVectorMachineModelParameter.ActualValue; }
+    }
+    public IntValue SamplesStart {
+      get { return SamplesStartParameter.ActualValue; }
+    }
+    public IntValue SamplesEnd {
+      get { return SamplesEndParameter.ActualValue; }
+    }
+    #endregion
+    public SupportVectorMachineModelEvaluator()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DataAnalysisProblemData>(DataAnalysisProblemDataParameterName, "The data analysis problem data to use for training."));
+      Parameters.Add(new LookupParameter<SupportVectorMachineModel>(ModelParameterName, "The result model generated by the SVM."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesStartParameterName, "The first index of the data set partition on which the SVM model should be evaluated."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesEndParameterName, "The last index of the data set partition on which the SVM model should be evaluated."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>(ValuesParameterName, "A matrix of original values of the target variable and output values of the SVM model."));
+    }
+
+    public override IOperation Apply() {
+      int targetVariableIndex = DataAnalysisProblemData.Dataset.GetVariableIndex(DataAnalysisProblemData.TargetVariable.Value);
+      int start = SamplesStart.Value;
+      int end = SamplesEnd.Value;
+
+      SVM.Problem problem = SupportVectorMachineUtil.CreateSvmProblem(DataAnalysisProblemData, start, end);
+      SVM.Problem scaledProblem = SupportVectorMachineModel.RangeTransform.Scale(problem);
+
+      double[,] values = new double[scaledProblem.Count, 2];
+      for (int i = 0; i < scaledProblem.Count; i++) {
+        values[i, 0] = DataAnalysisProblemData.Dataset[start + i, targetVariableIndex];
+        values[i, 1] = SVM.Prediction.Predict(SupportVectorMachineModel.Model, scaledProblem.X[i]);
+      }
+
+      ValuesParameter.ActualValue = new DoubleMatrix(values);
+      return base.Apply();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineUtil.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineUtil.cs	(revision 3842)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/SupportVectorMachine/SupportVectorMachineUtil.cs	(revision 3842)
@@ -0,0 +1,63 @@
+﻿#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.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Problems.DataAnalysis.SupportVectorMachine {
+  public class SupportVectorMachineUtil {
+    /// <summary>
+    /// Transforms <paramref name="problemData"/> into a data structure as needed by libSVM.
+    /// </summary>
+    /// <param name="problemData">The problem data to transform</param>
+    /// <param name="start">The index of the first row of <paramref name="problemData"/> to copy to the output.</param>
+    /// <param name="end">The last of the first row of <paramref name="problemData"/> to copy to the output.</param>
+    /// <returns>A problem data type that can be used to train a support vector machine.</returns>
+    public static SVM.Problem CreateSvmProblem(DataAnalysisProblemData problemData, int start, int end) {
+      int rowCount = end - start;
+      var targetVector = problemData.Dataset.GetVariableValues(problemData.TargetVariable.Value, start, end);
+
+      SVM.Node[][] nodes = new SVM.Node[targetVector.Length][];
+      List<SVM.Node> tempRow;
+      int maxNodeIndex = 0;
+      for (int row = 0; row < rowCount; row++) {
+        tempRow = new List<SVM.Node>();
+        foreach (var inputVariable in problemData.InputVariables) {
+          int col = problemData.Dataset.GetVariableIndex(inputVariable.Value);
+          double value = problemData.Dataset[start + row, col];
+          if (!double.IsNaN(value)) {
+            int nodeIndex = col + 1; // make sure the smallest nodeIndex = 1
+            tempRow.Add(new SVM.Node(nodeIndex, value));
+            if (nodeIndex > maxNodeIndex) maxNodeIndex = nodeIndex;
+          }
+        }
+        nodes[row] = tempRow.OrderBy(x => x.Index).ToArray(); // make sure the values are sorted by node index
+      }
+
+      return new SVM.Problem(targetVector.Length, targetVector, nodes, maxNodeIndex);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab/3.3/Files.txt
===================================================================
--- /trunk/sources/HeuristicLab/3.3/Files.txt	(revision 3841)
+++ /trunk/sources/HeuristicLab/3.3/Files.txt	(revision 3842)
@@ -67,4 +67,7 @@
 HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\2.5.0\HeuristicLab.ALGLIB-2.5.0:HeuristicLab.ALGLIb-2.5.0.dll
 HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\2.5.0\HeuristicLab.ALGLIB-2.5.0:ALGLIB License-2.5.0.txt
+HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\HeuristicLab.LibSVM-1.6.3:HeuristicLab.LibSVM-1.6.3.dll
+HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\HeuristicLab.LibSVM-1.6.3:LibSVM-1.6.3.dll
+HeuristicLab.ExtLibs\HeuristicLab.LibSVM\1.6.3\HeuristicLab.LibSVM-1.6.3:SVM.NET-1.6.3 License.txt
 
 HeuristicLab.ExtLibs\HeuristicLab.log4net\1.2.10.0:HeuristicLab.log4net-1.2.10.0.dll
