Index: trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 5877)
+++ trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 5933)
@@ -12,5 +12,6 @@
     <AssemblyName>HeuristicLab.Analysis-3.3</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
-    <TargetFrameworkProfile></TargetFrameworkProfile>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
     <FileAlignment>512</FileAlignment>
     <SignAssembly>true</SignAssembly>
@@ -125,4 +126,5 @@
     <Compile Include="DataVisualization\HeatMap.cs" />
     <Compile Include="DataVisualization\HeatMapHistory.cs" />
+    <Compile Include="MultidimensionalScaling\MultidimensionalScaling.cs" />
     <Compile Include="MultiObjective\RankBasedParetoFrontAnalyzer.cs" />
     <Compile Include="MultiObjective\ParetoFrontAnalyzer.cs" />
@@ -164,4 +166,8 @@
       <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
       <Name>HeuristicLab.Data-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\3.1.0\ALGLIB-3.1.0\ALGLIB-3.1.0.csproj">
+      <Project>{FC841674-62A7-4055-BE91-E41944B6C606}</Project>
+      <Name>ALGLIB-3.1.0</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
Index: trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLabAnalysisPlugin.cs.frame
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLabAnalysisPlugin.cs.frame	(revision 5877)
+++ trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLabAnalysisPlugin.cs.frame	(revision 5933)
@@ -28,4 +28,5 @@
   [Plugin("HeuristicLab.Analysis", "3.3.3.$WCREV$")]
   [PluginFile("HeuristicLab.Analysis-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.1")]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
Index: trunk/sources/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 5933)
@@ -0,0 +1,171 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Data;
+
+namespace HeuristicLab.Analysis {
+  public static class MultidimensionalScaling {
+
+    /// <summary>
+    /// Performs the Kruskal-Shepard algorithm and applies a gradient descent method
+    /// to fit the coordinates such that the difference between the fit distances
+    /// and the dissimilarities becomes minimal.
+    /// </summary>
+    /// <remarks>
+    /// It will initialize the coordinates in a deterministic fashion such that all initial points are equally spaced on a circle.
+    /// </remarks>
+    /// <param name="dissimilarities">A symmetric NxN matrix that specifies the dissimilarities between each element i and j. Diagonal elements are ignored.</param>
+    /// 
+    /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns>
+    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities) {
+      if (dissimilarities == null) throw new ArgumentNullException("dissimilarities");
+      if (dissimilarities.Rows != dissimilarities.Columns) throw new ArgumentException("Dissimilarities must be a square matrix.", "dissimilarities");
+
+      int dimension = dissimilarities.Rows;
+      if (dimension == 1) return new DoubleMatrix(new double[,] { { 0, 0 } });
+      else if (dimension == 2) return new DoubleMatrix(new double[,] { { 0, 0 }, { 0, dissimilarities[0, 1] } });
+
+      DoubleMatrix coordinates = new DoubleMatrix(dimension, 2);
+      double rad = (2 * Math.PI) / coordinates.Rows;
+      for (int i = 0; i < dimension; i++) {
+        coordinates[i, 0] = 10 * Math.Cos(rad * i);
+        coordinates[i, 1] = 10 * Math.Sin(rad * i);
+      }
+
+      return KruskalShepard(dissimilarities, coordinates);
+    }
+
+    /// <summary>
+    /// Performs the Kruskal-Shepard algorithm and applies a gradient descent method
+    /// to fit the coordinates such that the difference between the fit distances
+    /// and the dissimilarities is minimal.
+    /// </summary>
+    /// <remarks>
+    /// It will use a pre-initialized x,y-coordinates matrix as a starting point of the gradient descent.
+    /// </remarks>
+    /// <param name="dissimilarities">A symmetric NxN matrix that specifies the dissimilarities between each element i and j. Diagonal elements are ignored.</param>
+    /// <param name="coordinates">The Nx2 matrix of initial coordinates.</param>
+    /// <param name="maximumIterations">The number of iterations for which the algorithm should run.
+    /// In every iteration it tries to find the best location for every item.</param>
+    /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns>
+    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities, DoubleMatrix coordinates, int maximumIterations = 20) {
+      int dimension = dissimilarities.Rows;
+      if (dimension != dissimilarities.Columns || coordinates.Rows != dimension) throw new ArgumentException("The number of coordinates and the number of rows and columns in the dissimilarities matrix do not match.");
+
+      double epsg = 1e-7;
+      double epsf = 0;
+      double epsx = 0;
+      int maxits = 100;
+      alglib.mincgstate state = null;
+      alglib.mincgreport rep;
+
+      for (int iterations = 0; iterations < maximumIterations; iterations++) {
+        bool changed = false;
+        for (int i = 0; i < dimension; i++) {
+          double[] c = new double[] { coordinates[i, 0], coordinates[i, 1] };
+
+          try {
+            if ((iterations == 0 && i == 0)) {
+              alglib.mincgcreate(c, out state);
+              alglib.mincgsetcond(state, epsg, epsf, epsx, maxits);
+            } else {
+              alglib.mincgrestartfrom(state, c);
+            }
+            alglib.mincgoptimize(state, StressGradient, null, new Info(coordinates, dissimilarities, i));
+            alglib.mincgresults(state, out c, out rep);
+          } catch (alglib.alglibexception) { }
+          if (!double.IsNaN(c[0]) && !double.IsNaN(c[1])) {
+            changed = changed || (coordinates[i, 0] != c[0]) || (coordinates[i, 1] != c[1]);
+            coordinates[i, 0] = c[0];
+            coordinates[i, 1] = c[1];
+          }
+        }
+        if (!changed) break;
+      }
+      return coordinates;
+    }
+
+    // computes the function and the gradient of the raw stress function.
+    private static void StressGradient(double[] x, ref double func, double[] grad, object obj) {
+      func = 0; grad[0] = 0; grad[1] = 0;
+      Info info = (obj as Info);
+      for (int i = 0; i < info.Coordinates.Rows; i++) {
+        double c = info.Dissimilarities[info.Row, i];
+        if (i != info.Row) {
+          double a = info.Coordinates[i, 0];
+          double b = info.Coordinates[i, 1];
+          func += Stress(x, c, a, b);
+          grad[0] += ((2 * x[0] - 2 * a) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[0] + 2 * a * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a);
+          grad[1] += ((2 * x[1] - 2 * b) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[1] + 2 * b * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a);
+        }
+      }
+    }
+
+    private static double Stress(double[] x, double distance, double xCoord, double yCoord) {
+      return Stress(x[0], x[1], distance, xCoord, yCoord);
+    }
+
+    private static double Stress(double x, double y, double distance, double otherX, double otherY) {
+      double d = Math.Sqrt((x - otherX) * (x - otherX)
+                         + (y - otherY) * (y - otherY));
+      return (d - distance) * (d - distance);
+    }
+
+    /// <summary>
+    /// This method computes the normalized raw-stress value according to Groenen and van de Velden 2004. "Multidimensional Scaling". Technical report EI 2004-15.
+    /// </summary>
+    /// <remarks>
+    /// Throws an ArgumentException when the <paramref name="dissimilarities"/> matrix is not symmetric.
+    /// </remarks>
+    /// 
+    /// <param name="dissimilarities">The matrix with the dissimilarities.</param>
+    /// <param name="coordinates">The actual location of the points.</param>
+    /// <returns>The normalized raw-stress value that describes the goodness-of-fit between the distances in the points and the size of the dissimilarities. If the value is &lt; 0.1 the fit is generally considered good. If between 0.1 and 0.2 it is considered acceptable, but the usefulness of the scaling with higher values is doubtful.</returns>
+    public static double CalculateNormalizedStress(DoubleMatrix dissimilarities, DoubleMatrix coordinates) {
+      int dimension = dissimilarities.Rows;
+      if (dimension != dissimilarities.Columns || dimension != coordinates.Rows) throw new ArgumentException("The number of coordinates and the number of rows and columns in the dissimilarities matrix do not match.");
+      double stress = 0, normalization = 0;
+      for (int i = 0; i < dimension - 1; i++) {
+        for (int j = i + 1; j < dimension; j++) {
+          if (dissimilarities[i, j] != dissimilarities[j, i]) throw new ArgumentException("Dissimilarities is not a symmetric matrix.", "dissimilarities");
+          if (dissimilarities[i, j] != 0) {
+            stress += Stress(coordinates[i, 0], coordinates[i, 1], dissimilarities[i, j], coordinates[j, 0], coordinates[j, 1]);
+            normalization += (dissimilarities[i, j] * dissimilarities[i, j]);
+          }
+        }
+      }
+      return stress / normalization;
+    }
+
+    private class Info {
+      public DoubleMatrix Coordinates { get; set; }
+      public DoubleMatrix Dissimilarities { get; set; }
+      public int Row { get; set; }
+
+      public Info(DoubleMatrix c, DoubleMatrix d, int r) {
+        Coordinates = c;
+        Dissimilarities = d;
+        Row = r;
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/Tests/HeuristicLab.Analysis.Tests-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/Tests/HeuristicLab.Analysis.Tests-3.3.csproj	(revision 5933)
+++ trunk/sources/HeuristicLab.Analysis/3.3/Tests/HeuristicLab.Analysis.Tests-3.3.csproj	(revision 5933)
@@ -0,0 +1,142 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>
+    </ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{34C967E5-EEB1-4502-8035-122EDDEF44CB}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Analysis.Tests</RootNamespace>
+    <AssemblyName>HeuristicLab.Analysis.Tests</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+  </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|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.Analysis.Tests.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.Analysis.Tests.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\HeuristicLab.Analysis.Tests.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+    <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Release\HeuristicLab.Analysis.Tests.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+    </ProjectReference>
+    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="MultidimensionalScalingTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\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>
+  -->
+</Project>
Index: trunk/sources/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs	(revision 5933)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Data;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Analysis.Tests {
+  [TestClass]
+  public class MultidimensionalScalingTest {
+    [TestMethod]
+    public void TestGoodnessOfFit() {
+      double stress;
+      DoubleMatrix distances3 = new DoubleMatrix(3, 3);
+      // Example 1: A right triangle
+      distances3[0, 1] = distances3[1, 0] = 3;
+      distances3[0, 2] = distances3[2, 0] = 4;
+      distances3[1, 2] = distances3[2, 1] = 5;
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distances3,
+        MultidimensionalScaling.KruskalShepard(distances3));
+      Assert.IsTrue(stress < 0.1);
+      // Example 2: An arbitrary triangle
+      distances3[0, 1] = distances3[1, 0] = 8;
+      distances3[0, 2] = distances3[2, 0] = 6.4;
+      distances3[1, 2] = distances3[2, 1] = 5;
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distances3,
+        MultidimensionalScaling.KruskalShepard(distances3));
+      Assert.IsTrue(stress < 0.1);
+      DoubleMatrix distances4 = new DoubleMatrix(4, 4);
+      // Example 3: A small square
+      distances4[0, 1] = distances4[1, 0] = 1;
+      distances4[0, 2] = distances4[2, 0] = Math.Sqrt(2);
+      distances4[0, 3] = distances4[3, 0] = 1;
+      distances4[1, 2] = distances4[2, 1] = 1;
+      distances4[1, 3] = distances4[3, 1] = Math.Sqrt(2);
+      distances4[2, 3] = distances4[3, 2] = 1;
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distances4,
+        MultidimensionalScaling.KruskalShepard(distances4));
+      Assert.IsTrue(stress < 0.1);
+      // Example 4: A large square
+      distances4[0, 1] = distances4[1, 0] = 1000;
+      distances4[0, 2] = distances4[2, 0] = Math.Sqrt(2000000);
+      distances4[0, 3] = distances4[3, 0] = 1000;
+      distances4[1, 2] = distances4[2, 1] = 1000;
+      distances4[1, 3] = distances4[3, 1] = Math.Sqrt(2000000);
+      distances4[2, 3] = distances4[3, 2] = 1000;
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distances4,
+        MultidimensionalScaling.KruskalShepard(distances4));
+      Assert.IsTrue(stress < 0.1);
+      // Example 5: An arbitrary cloud of 8 points in a plane
+      DoubleMatrix distancesK = GetDistances(new double[,] { { 2, 1 }, { 5, 2 }, { 7, 1 }, { 4, 0 }, { 3, 3 }, { 4, 2 }, { 1, 8 }, { 6, 3 } });
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distancesK,
+        MultidimensionalScaling.KruskalShepard(distancesK));
+      Assert.IsTrue(stress < 0.1);
+      // Example 6: A tetrahedron
+      distancesK = GetDistances(new double[,] { { 0, 0, 0 }, { 4, 0, 0 }, { 2, 3.4641, 0 }, { 2, 1.1547, 3.2660 } });
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distancesK,
+        MultidimensionalScaling.KruskalShepard(distancesK));
+      Assert.IsTrue(stress < 0.1);
+    }
+
+    internal DoubleMatrix GetDistances(double[,] coordinates) {
+      int dimension = coordinates.GetLength(0);
+      DoubleMatrix distances = new DoubleMatrix(dimension, dimension);
+      for (int i = 0; i < dimension - 1; i++)
+        for (int j = i + 1; j < dimension; j++) {
+          double sum = 0;
+          for (int k = 0; k < coordinates.GetLength(1); k++)
+            sum += (coordinates[i, k] - coordinates[j, k]) * (coordinates[i, k] - coordinates[j, k]);
+          distances[i, j] = distances[j, i] = Math.Sqrt(sum);
+        }
+      return distances;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/Tests/Properties/AssemblyInfo.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/Tests/Properties/AssemblyInfo.cs	(revision 5933)
+++ trunk/sources/HeuristicLab.Analysis/3.3/Tests/Properties/AssemblyInfo.cs	(revision 5933)
@@ -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("HeuristicLab.Analysis.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("HeuristicLab.Analysis.Tests")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("f721bb92-ee65-4014-a57a-193c6f6a1219")]
+
+// 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.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
