Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 14784)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 14785)
@@ -334,6 +334,6 @@
     <Compile Include="Interfaces\TSNEInterfaces\IDataPoint.cs" />
     <Compile Include="Interfaces\TSNEInterfaces\IDistance.cs" />
-    <Compile Include="Interfaces\TSNEInterfaces\ISPTree.cs" />
-    <Compile Include="Interfaces\TSNEInterfaces\IVPTree.cs" />
+    <Compile Include="Interfaces\TSNEInterfaces\ISpacePartitioningTree.cs" />
+    <Compile Include="Interfaces\TSNEInterfaces\IVantagePointTree.cs" />
     <Compile Include="kMeans\KMeansClustering.cs" />
     <Compile Include="kMeans\KMeansClusteringModel.cs" />
@@ -419,15 +419,14 @@
     <Compile Include="TimeSeries\AutoregressiveModeling.cs" />
     <Compile Include="TSNE\Cell.cs" />
-    <Compile Include="TSNE\DataPoint.cs" />
     <Compile Include="TSNE\Distances\DistanceBase.cs" />
-    <Compile Include="TSNE\Distances\DataPointDistance.cs" />
     <Compile Include="TSNE\Distances\EuclideanDistance.cs" />
+    <Compile Include="TSNE\Distances\IndexedItemDistance.cs" />
     <Compile Include="TSNE\Distances\InnerProductDistance.cs" />
     <Compile Include="TSNE\PriorityQueue.cs" />
-    <Compile Include="TSNE\SPtree.cs" />
-    <Compile Include="TSNE\TSNE.cs" />
+    <Compile Include="TSNE\SpacePartitioningTree.cs" />
+    <Compile Include="TSNE\TSNEAlgorithm.cs" />
     <Compile Include="TSNE\TSNEStatic.cs" />
     <Compile Include="TSNE\TSNEUtils.cs" />
-    <Compile Include="TSNE\VPTree.cs" />
+    <Compile Include="TSNE\VantagePointTree.cs" />
   </ItemGroup>
   <ItemGroup>
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/ISPTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/ISPTree.cs	(revision 14784)
+++ 	(revision )
@@ -1,39 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Common;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  public interface ISPTree : IDeepCloneable {
-
-    double[,] Data { set; }
-    int GetDepth();
-    ISPTree GetParent();
-    bool Insert(int newIndex);
-    void Subdivide();
-    bool IsCorrect();
-    void GetAllIndices(int[] indices);
-    int GetAllIndices(int[] indices, int loc);
-    void ComputeNonEdgeForces(int pointIndex, double theta, double[] negF, double[] sumQ);
-    void ComputeEdgeForces(int[] rowP, int[] colP, double[] valP, int n, double[,] posF);
-
-  }
-}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/ISpacePartitioningTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/ISpacePartitioningTree.cs	(revision 14785)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/ISpacePartitioningTree.cs	(revision 14785)
@@ -0,0 +1,39 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  public interface ISpacePartitioningTree {
+
+    double[,] Data { set; }
+    int GetDepth();
+    ISpacePartitioningTree GetParent();
+    bool Insert(int newIndex);
+    void Subdivide();
+    bool IsCorrect();
+    void GetAllIndices(int[] indices);
+    int GetAllIndices(int[] indices, int loc);
+    void ComputeNonEdgeForces(int pointIndex, double theta, double[] negF, double[] sumQ);
+    void ComputeEdgeForces(int[] rowP, int[] colP, double[] valP, int n, double[,] posF);
+
+  }
+}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/IVPTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/IVPTree.cs	(revision 14784)
+++ 	(revision )
@@ -1,30 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System.Collections.Generic;
-using HeuristicLab.Common;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  public interface IVPTree<T> : IDeepCloneable {
-    void Create(IEnumerable<T> items);
-    void Search(T target, int k, out List<T> results, out List<double> distances);
-  }
-}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/IVantagePointTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/IVantagePointTree.cs	(revision 14785)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/Interfaces/TSNEInterfaces/IVantagePointTree.cs	(revision 14785)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  public interface IVantagePointTree<T> {
+    void Search(T target, int k, out IList<T> results, out IList<double> distances);
+  }
+}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/DataPoint.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/DataPoint.cs	(revision 14784)
+++ 	(revision )
@@ -1,91 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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/>.
- */
-
-//Code is based on an implementation from Laurens van der Maaten
-
-/*
-*
-* Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-*    must display the following acknowledgement:
-*    This product includes software developed by the Delft University of Technology.
-* 4. Neither the name of the Delft University of Technology nor the names of
-*    its contributors may be used to endorse or promote products derived from
-*    this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS
-* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-* EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-* OF SUCH DAMAGE.
-*
-*/
-#endregion
-
-using HeuristicLab.Common;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  [StorableClass]
-  public class DataPoint<T> : DeepCloneable, IDataPoint<T> where T : class, IDeepCloneable {
-    #region properties
-    [Storable]
-    private int ind;
-    [Storable]
-    public T X { get; private set; }
-
-    public int Index
-    {
-      get { return ind; }
-    }
-    #endregion
-
-    #region HLConstructors & Cloning
-    [StorableConstructor]
-    protected DataPoint(bool deserializing) { }
-    protected DataPoint(DataPoint<T> original, Cloner cloner)
-      : base(original, cloner) {
-      ind = original.ind;
-      X = cloner.Clone(original.X);
-    }
-    public override IDeepCloneable Clone(Cloner cloner) { return new DataPoint<T>(this, cloner); }
-    public DataPoint() : this(1, null) { }
-    public DataPoint(int ind, T x) {
-      this.ind = ind;
-      X = (T)x.Clone();
-    }
-    #endregion
-
-  }
-}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DataPointDistance.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DataPointDistance.cs	(revision 14784)
+++ 	(revision )
@@ -1,53 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  [StorableClass]
-  [Item("DataPointDistance", "A distance wrapper for DataPoints")]
-  internal class DataPointDistance<T> : DistanceBase<IDataPoint<T>> where T : class {
-
-    #region properties
-    [Storable]
-    private IDistance<T> dist;
-    #endregion
-
-    #region HLConstructors & Cloning
-    [StorableConstructor]
-    protected DataPointDistance(bool deserializing) : base(deserializing) { }
-    protected DataPointDistance(DataPointDistance<T> original, Cloner cloner) : base(original, cloner) {
-      dist = cloner.Clone(original.dist);
-    }
-    public override IDeepCloneable Clone(Cloner cloner) { return new DataPointDistance<T>(this, cloner); }
-    public DataPointDistance(IDistance<T> distance) {
-      dist = distance;
-    }
-    #endregion
-
-    public override double Get(IDataPoint<T> a, IDataPoint<T> b) {
-      return dist.Get(a.X, b.X);
-    }
-  }
-}
-
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/IndexedItemDistance.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/IndexedItemDistance.cs	(revision 14785)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/IndexedItemDistance.cs	(revision 14785)
@@ -0,0 +1,51 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  [Item("IndexedItemDistance", "A distance wrapper for indexed items")]
+  internal class IndexedItemDistance<T> : DistanceBase<IndexedItem<T>> {
+    [Storable]
+    private readonly IDistance<T> dist;
+
+    #region HLConstructors & Cloning
+    [StorableConstructor]
+    protected IndexedItemDistance(bool deserializing) : base(deserializing) { }
+    protected IndexedItemDistance(IndexedItemDistance<T> original, Cloner cloner) : base(original, cloner) {
+      dist = cloner.Clone(original.dist);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new IndexedItemDistance<T>(this, cloner); }
+    public IndexedItemDistance(IDistance<T> distance) {
+      dist = distance;
+    }
+    #endregion
+
+    public override double Get(IndexedItem<T> a, IndexedItem<T> b) {
+      return dist.Get(a.Value, b.Value);
+    }
+  }
+}
+
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/PriorityQueue.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/PriorityQueue.cs	(revision 14784)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/PriorityQueue.cs	(revision 14785)
@@ -25,4 +25,5 @@
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
+  // TODO: move to HeuristicLab.Collections
 
   // Code Taken from branch: RoutePlanning, Heap4
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/SPtree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/SPtree.cs	(revision 14784)
+++ 	(revision )
@@ -1,330 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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/>.
- */
-
-//Code is based on an implementation from Laurens van der Maaten
-
-/*
-*
-* Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-*    must display the following acknowledgement:
-*    This product includes software developed by the Delft University of Technology.
-* 4. Neither the name of the Delft University of Technology nor the names of
-*    its contributors may be used to endorse or promote products derived from
-*    this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS
-* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-* EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-* OF SUCH DAMAGE.
-*
-*/
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  /// <summary>
-  /// Space partitioning tree
-  /// </summary>
-  [StorableClass]
-  public class SPTree : DeepCloneable, ISPTree {
-    private const uint QT_NODE_CAPACITY = 1;
-
-    #region properties
-    [Storable]
-    private double[] buff;
-    [Storable]
-    private ISPTree parent;
-    [Storable]
-    private int dimension;
-    [Storable]
-    private bool isLeaf;
-    [Storable]
-    private uint size;
-    [Storable]
-    private uint cumulativeSize;
-
-    // Axis-aligned bounding box stored as a center with half-dimensions to represent the boundaries of this quad tree
-    [Storable]
-    private ICell boundary;
-
-    // Indices in this space-partitioning tree node, corresponding center-of-mass, and list of all children
-    [Storable]
-    public double[,] Data { private get; set; }
-    [Storable]
-    private double[] centerOfMass;
-    [Storable]
-    private int[] index = new int[QT_NODE_CAPACITY];
-
-    // Children
-    private ISPTree[] children;
-    [Storable]
-    private uint noChildren;
-    #endregion
-
-    #region HLConstructors & Cloning
-    [StorableConstructor]
-    protected SPTree(bool deserializing) { }
-    protected SPTree(SPTree original, Cloner cloner)
-      : base(original, cloner) {
-      buff = original.buff.Select(x => x).ToArray();
-      parent = cloner.Clone(original.parent);
-      dimension = original.dimension;
-      isLeaf = original.isLeaf;
-      size = original.size;
-      cumulativeSize = original.cumulativeSize;
-      boundary = cloner.Clone(original.boundary);
-      if (original.Data != null) {
-        Data = new double[size, dimension];
-        Buffer.BlockCopy(original.Data, 0, Data, 0, original.Data.Length * sizeof(double));
-      }
-      centerOfMass = original.centerOfMass.Select(x => x).ToArray();
-      index = original.index.Select(x => x).ToArray();
-      children = original.children.Select(cloner.Clone).ToArray();
-      noChildren = original.noChildren;
-    }
-    public override IDeepCloneable Clone(Cloner cloner) { return new SPTree(this, cloner); }
-
-    public SPTree(double[,] inpData) {
-      var d = inpData.GetLength(1);
-      var n = inpData.GetLength(0);
-      var meanY = new double[d];
-      var minY = new double[d];
-      for (var i = 0; i < d; i++) minY[i] = double.MaxValue;
-      var maxY = new double[d];
-      for (var i = 0; i < d; i++) maxY[i] = double.MinValue;
-      for (uint i = 0; i < n; i++) {
-        for (uint j = 0; j < d; j++) {
-          meanY[j] = inpData[i, j];
-          if (inpData[i, j] < minY[j]) minY[j] = inpData[i, j];
-          if (inpData[i, j] > maxY[j]) maxY[j] = inpData[i, j];
-        }
-      }
-      for (var i = 0; i < d; i++) meanY[i] /= n;
-      var width = new double[d];
-      for (var i = 0; i < d; i++) width[i] = Math.Max(maxY[i] - meanY[i], meanY[i] - maxY[i]) + 1e-5;
-      Init(null, inpData, meanY, width);
-      Fill(n);
-    }
-
-    public SPTree(double[,] inpData, IEnumerable<double> impCorner, IEnumerable<double> impWith) {
-      Init(null, inpData, impCorner, impWith);
-    }
-    public SPTree(ISPTree parent, double[,] inpData, IEnumerable<double> impCorner, IEnumerable<double> impWith) {
-      Init(parent, inpData, impCorner, impWith);
-    }
-    #endregion
-
-    public ISPTree GetParent() {
-      return parent;
-    }
-
-    public bool Insert(int newIndex) {
-      // Ignore objects which do not belong in this quad tree
-      var point = new double[dimension];
-      Buffer.BlockCopy(Data, sizeof(double) * dimension * newIndex, point, 0, sizeof(double) * dimension);
-      if (!boundary.ContainsPoint(point)) return false;
-      cumulativeSize++;
-      // Online update of cumulative size and center-of-mass
-      var mult1 = (double)(cumulativeSize - 1) / cumulativeSize;
-      var mult2 = 1.0 / cumulativeSize;
-      for (var i = 0; i < dimension; i++) centerOfMass[i] *= mult1;
-      for (var i = 0; i < dimension; i++) centerOfMass[i] += mult2 * point[i];
-
-      // If there is space in this quad tree and it is a leaf, add the object here
-      if (isLeaf && size < QT_NODE_CAPACITY) {
-        index[size] = newIndex;
-        size++;
-        return true;
-      }
-
-      // Don't add duplicates for now (this is not very nice)
-      var anyDuplicate = false;
-      for (uint n = 0; n < size; n++) {
-        var duplicate = true;
-        for (var d = 0; d < dimension; d++) {
-          if (Math.Abs(point[d] - Data[index[n], d]) < double.Epsilon) continue;
-          duplicate = false; break;
-        }
-        anyDuplicate = anyDuplicate | duplicate;
-      }
-      if (anyDuplicate) return true;
-
-      // Otherwise, we need to subdivide the current cell
-      if (isLeaf) Subdivide();
-      // Find out where the point can be inserted
-      for (var i = 0; i < noChildren; i++) {
-        if (children[i].Insert(newIndex)) return true;
-      }
-
-      // Otherwise, the point cannot be inserted (this should never happen)
-      return false;
-    }
-
-    public void Subdivide() {
-      // Create new children
-      var newCorner = new double[dimension];
-      var newWidth = new double[dimension];
-      for (var i = 0; i < noChildren; i++) {
-        var div = 1;
-        for (var d = 0; d < dimension; d++) {
-          newWidth[d] = .5 * boundary.GetWidth(d);
-          if ((i / div) % 2 == 1) newCorner[d] = boundary.GetCorner(d) - .5 * boundary.GetWidth(d);
-          else newCorner[d] = boundary.GetCorner(d) + .5 * boundary.GetWidth(d);
-          div *= 2;
-        }
-        children[i] = new SPTree(this, Data, newCorner, newWidth);
-      }
-
-      // Move existing points to correct children
-      for (var i = 0; i < size; i++) {
-        var success = false;
-        for (var j = 0; j < noChildren; j++) {
-          if (!success) success = children[j].Insert(index[i]);
-        }
-        index[i] = int.MaxValue;
-      }
-
-      // Empty parent node
-      size = 0;
-      isLeaf = false;
-    }
-
-    public bool IsCorrect() {
-      var row = new double[dimension];
-      for (var n = 0; n < size; n++) Buffer.BlockCopy(Data, sizeof(double) * dimension * n, row, 0, sizeof(double) * dimension);
-      if (!boundary.ContainsPoint(row)) return false;
-      if (isLeaf) return true;
-      var correct = true;
-      for (var i = 0; i < noChildren; i++) correct = correct && children[i].IsCorrect();
-      return correct;
-    }
-
-    public void GetAllIndices(int[] indices) {
-      GetAllIndices(indices, 0);
-    }
-
-    public int GetAllIndices(int[] indices, int loc) {
-      // Gather indices in current quadrant
-      for (var i = 0; i < size; i++) indices[loc + i] = index[i];
-      loc += (int)size;
-      // Gather indices in children
-      if (isLeaf) return loc;
-      for (var i = 0; i < noChildren; i++) loc = children[i].GetAllIndices(indices, loc);
-      return loc;
-    }
-
-    public int GetDepth() {
-      return isLeaf ? 1 : 1 + children.Max(x => x.GetDepth());
-    }
-
-    public void ComputeNonEdgeForces(int pointIndex, double theta, double[] negF, double[] sumQ) {
-      // Make sure that we spend no time on empty nodes or self-interactions
-      if (cumulativeSize == 0 || (isLeaf && size == 1 && index[0] == pointIndex)) return;
-
-      // Compute distance between point and center-of-mass
-      var D = .0;
-      for (var d = 0; d < dimension; d++) buff[d] = Data[pointIndex, d] - centerOfMass[d];
-      for (var d = 0; d < dimension; d++) D += buff[d] * buff[d];
-
-      // Check whether we can use this node as a "summary"
-      var maxWidth = 0.0;
-      for (var d = 0; d < dimension; d++) {
-        var curWidth = boundary.GetWidth(d);
-        maxWidth = (maxWidth > curWidth) ? maxWidth : curWidth;
-      }
-      if (isLeaf || maxWidth / Math.Sqrt(D) < theta) {
-
-        // Compute and add t-SNE force between point and current node
-        D = 1.0 / (1.0 + D);
-        var mult = cumulativeSize * D;
-        sumQ[0] += mult;
-        mult *= D;
-        for (var d = 0; d < dimension; d++) negF[d] += mult * buff[d];
-      } else {
-
-        // Recursively apply Barnes-Hut to children
-        for (var i = 0; i < noChildren; i++) children[i].ComputeNonEdgeForces(pointIndex, theta, negF, sumQ);
-      }
-    }
-
-    public void ComputeEdgeForces(int[] rowP, int[] colP, double[] valP, int n, double[,] posF) {
-      // Loop over all edges in the graph
-      for (var k = 0; k < n; k++) {
-        for (var i = rowP[k]; i < rowP[k + 1]; i++) {
-
-          // Compute pairwise distance and Q-value
-          var d = 1.0;
-          for (var j = 0; j < dimension; j++) buff[j] = Data[k, j] - Data[colP[i], j];
-          for (var j = 0; j < dimension; j++) d += buff[j] * buff[j];
-          d = valP[i] / d;
-
-          // Sum positive force
-          for (var j = 0; j < dimension; j++) posF[k, j] += d * buff[j];
-        }
-      }
-    }
-
-    #region Helpers
-    private void Fill(int n) {
-      for (var i = 0; i < n; i++) Insert(i);
-    }
-    private void Init(ISPTree p, double[,] inpData, IEnumerable<double> inpCorner, IEnumerable<double> inpWidth) {
-      parent = p;
-      dimension = inpData.GetLength(1);
-      noChildren = 2;
-      for (uint i = 1; i < dimension; i++) noChildren *= 2;
-      Data = inpData;
-      isLeaf = true;
-      size = 0;
-      cumulativeSize = 0;
-      boundary = new Cell((uint)dimension);
-      inpCorner.ForEach((i, x) => boundary.SetCorner(i, x));
-      inpWidth.ForEach((i, x) => boundary.SetWidth(i, x));
-
-      children = new ISPTree[noChildren];
-      centerOfMass = new double[dimension];
-      buff = new double[dimension];
-
-    }
-    #endregion
-
-  }
-}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/SpacePartitioningTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/SpacePartitioningTree.cs	(revision 14785)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/SpacePartitioningTree.cs	(revision 14785)
@@ -0,0 +1,330 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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/>.
+ */
+
+//Code is based on an implementation from Laurens van der Maaten
+
+/*
+*
+* Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology)
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+* 3. All advertising materials mentioning features or use of this software
+*    must display the following acknowledgement:
+*    This product includes software developed by the Delft University of Technology.
+* 4. Neither the name of the Delft University of Technology nor the names of
+*    its contributors may be used to endorse or promote products derived from
+*    this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS
+* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+* EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+* OF SUCH DAMAGE.
+*
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Space partitioning tree (SPTree)
+  /// </summary>
+  [StorableClass]
+  public class SpacePartitioningTree : DeepCloneable, ISpacePartitioningTree {
+    private const uint QT_NODE_CAPACITY = 1;
+
+    #region properties
+    [Storable]
+    private double[] buff;
+    [Storable]
+    private SpacePartitioningTree parent;
+    [Storable]
+    private int dimension;
+    [Storable]
+    private bool isLeaf;
+    [Storable]
+    private uint size;
+    [Storable]
+    private uint cumulativeSize;
+
+    // Axis-aligned bounding box stored as a center with half-dimensions to represent the boundaries of this quad tree
+    [Storable]
+    private ICell boundary;
+
+    // Indices in this space-partitioning tree node, corresponding center-of-mass, and list of all children
+    [Storable]
+    public double[,] Data { private get; set; }
+    [Storable]
+    private double[] centerOfMass;
+    [Storable]
+    private int[] index = new int[QT_NODE_CAPACITY];
+
+    // Children
+    private SpacePartitioningTree[] children;
+    [Storable]
+    private uint noChildren;
+    #endregion
+
+    #region HLConstructors & Cloning
+    [StorableConstructor]
+    protected SpacePartitioningTree(bool deserializing) { }
+    protected SpacePartitioningTree(SpacePartitioningTree original, Cloner cloner)
+      : base(original, cloner) {
+      buff = original.buff.Select(x => x).ToArray();
+      parent = cloner.Clone(original.parent);
+      dimension = original.dimension;
+      isLeaf = original.isLeaf;
+      size = original.size;
+      cumulativeSize = original.cumulativeSize;
+      boundary = cloner.Clone(original.boundary);
+      if (original.Data != null) {
+        Data = new double[size, dimension];
+        Buffer.BlockCopy(original.Data, 0, Data, 0, original.Data.Length * sizeof(double));
+      }
+      centerOfMass = original.centerOfMass.Select(x => x).ToArray();
+      index = original.index.Select(x => x).ToArray();
+      children = original.children.Select(cloner.Clone).ToArray();
+      noChildren = original.noChildren;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) { return new SpacePartitioningTree(this, cloner); }
+
+    public SpacePartitioningTree(double[,] inpData) {
+      var d = inpData.GetLength(1);
+      var n = inpData.GetLength(0);
+      var meanY = new double[d];
+      var minY = new double[d];
+      for (var i = 0; i < d; i++) minY[i] = double.MaxValue;
+      var maxY = new double[d];
+      for (var i = 0; i < d; i++) maxY[i] = double.MinValue;
+      for (uint i = 0; i < n; i++) {
+        for (uint j = 0; j < d; j++) {
+          meanY[j] = inpData[i, j];
+          if (inpData[i, j] < minY[j]) minY[j] = inpData[i, j];
+          if (inpData[i, j] > maxY[j]) maxY[j] = inpData[i, j];
+        }
+      }
+      for (var i = 0; i < d; i++) meanY[i] /= n;
+      var width = new double[d];
+      for (var i = 0; i < d; i++) width[i] = Math.Max(maxY[i] - meanY[i], meanY[i] - maxY[i]) + 1e-5;
+      Init(null, inpData, meanY, width);
+      Fill(n);
+    }
+
+    public SpacePartitioningTree(double[,] inpData, IEnumerable<double> impCorner, IEnumerable<double> impWith) {
+      Init(null, inpData, impCorner, impWith);
+    }
+    public SpacePartitioningTree(SpacePartitioningTree parent, double[,] inpData, IEnumerable<double> impCorner, IEnumerable<double> impWith) {
+      Init(parent, inpData, impCorner, impWith);
+    }
+    #endregion
+
+    public ISpacePartitioningTree GetParent() {
+      return parent;
+    }
+
+    public bool Insert(int newIndex) {
+      // Ignore objects which do not belong in this quad tree
+      var point = new double[dimension];
+      Buffer.BlockCopy(Data, sizeof(double) * dimension * newIndex, point, 0, sizeof(double) * dimension);
+      if (!boundary.ContainsPoint(point)) return false;
+      cumulativeSize++;
+      // Online update of cumulative size and center-of-mass
+      var mult1 = (double)(cumulativeSize - 1) / cumulativeSize;
+      var mult2 = 1.0 / cumulativeSize;
+      for (var i = 0; i < dimension; i++) centerOfMass[i] *= mult1;
+      for (var i = 0; i < dimension; i++) centerOfMass[i] += mult2 * point[i];
+
+      // If there is space in this quad tree and it is a leaf, add the object here
+      if (isLeaf && size < QT_NODE_CAPACITY) {
+        index[size] = newIndex;
+        size++;
+        return true;
+      }
+
+      // Don't add duplicates for now (this is not very nice)
+      var anyDuplicate = false;
+      for (uint n = 0; n < size; n++) {
+        var duplicate = true;
+        for (var d = 0; d < dimension; d++) {
+          if (Math.Abs(point[d] - Data[index[n], d]) < double.Epsilon) continue;
+          duplicate = false; break;
+        }
+        anyDuplicate = anyDuplicate | duplicate;
+      }
+      if (anyDuplicate) return true;
+
+      // Otherwise, we need to subdivide the current cell
+      if (isLeaf) Subdivide();
+      // Find out where the point can be inserted
+      for (var i = 0; i < noChildren; i++) {
+        if (children[i].Insert(newIndex)) return true;
+      }
+
+      // Otherwise, the point cannot be inserted (this should never happen)
+      return false;
+    }
+
+    public void Subdivide() {
+      // Create new children
+      var newCorner = new double[dimension];
+      var newWidth = new double[dimension];
+      for (var i = 0; i < noChildren; i++) {
+        var div = 1;
+        for (var d = 0; d < dimension; d++) {
+          newWidth[d] = .5 * boundary.GetWidth(d);
+          if ((i / div) % 2 == 1) newCorner[d] = boundary.GetCorner(d) - .5 * boundary.GetWidth(d);
+          else newCorner[d] = boundary.GetCorner(d) + .5 * boundary.GetWidth(d);
+          div *= 2;
+        }
+        children[i] = new SpacePartitioningTree(this, Data, newCorner, newWidth);
+      }
+
+      // Move existing points to correct children
+      for (var i = 0; i < size; i++) {
+        var success = false;
+        for (var j = 0; j < noChildren; j++) {
+          if (!success) success = children[j].Insert(index[i]);
+        }
+        index[i] = int.MaxValue;
+      }
+
+      // Empty parent node
+      size = 0;
+      isLeaf = false;
+    }
+
+    public bool IsCorrect() {
+      var row = new double[dimension];
+      for (var n = 0; n < size; n++) Buffer.BlockCopy(Data, sizeof(double) * dimension * n, row, 0, sizeof(double) * dimension);
+      if (!boundary.ContainsPoint(row)) return false;
+      if (isLeaf) return true;
+      var correct = true;
+      for (var i = 0; i < noChildren; i++) correct = correct && children[i].IsCorrect();
+      return correct;
+    }
+
+    public void GetAllIndices(int[] indices) {
+      GetAllIndices(indices, 0);
+    }
+
+    public int GetAllIndices(int[] indices, int loc) {
+      // Gather indices in current quadrant
+      for (var i = 0; i < size; i++) indices[loc + i] = index[i];
+      loc += (int)size;
+      // Gather indices in children
+      if (isLeaf) return loc;
+      for (var i = 0; i < noChildren; i++) loc = children[i].GetAllIndices(indices, loc);
+      return loc;
+    }
+
+    public int GetDepth() {
+      return isLeaf ? 1 : 1 + children.Max(x => x.GetDepth());
+    }
+
+    public void ComputeNonEdgeForces(int pointIndex, double theta, double[] negF, double[] sumQ) {
+      // Make sure that we spend no time on empty nodes or self-interactions
+      if (cumulativeSize == 0 || (isLeaf && size == 1 && index[0] == pointIndex)) return;
+
+      // Compute distance between point and center-of-mass
+      var D = .0;
+      for (var d = 0; d < dimension; d++) buff[d] = Data[pointIndex, d] - centerOfMass[d];
+      for (var d = 0; d < dimension; d++) D += buff[d] * buff[d];
+
+      // Check whether we can use this node as a "summary"
+      var maxWidth = 0.0;
+      for (var d = 0; d < dimension; d++) {
+        var curWidth = boundary.GetWidth(d);
+        maxWidth = (maxWidth > curWidth) ? maxWidth : curWidth;
+      }
+      if (isLeaf || maxWidth / Math.Sqrt(D) < theta) {
+
+        // Compute and add t-SNE force between point and current node
+        D = 1.0 / (1.0 + D);
+        var mult = cumulativeSize * D;
+        sumQ[0] += mult;
+        mult *= D;
+        for (var d = 0; d < dimension; d++) negF[d] += mult * buff[d];
+      } else {
+
+        // Recursively apply Barnes-Hut to children
+        for (var i = 0; i < noChildren; i++) children[i].ComputeNonEdgeForces(pointIndex, theta, negF, sumQ);
+      }
+    }
+
+    public void ComputeEdgeForces(int[] rowP, int[] colP, double[] valP, int n, double[,] posF) {
+      // Loop over all edges in the graph
+      for (var k = 0; k < n; k++) {
+        for (var i = rowP[k]; i < rowP[k + 1]; i++) {
+
+          // Compute pairwise distance and Q-value
+          var d = 1.0;
+          for (var j = 0; j < dimension; j++) buff[j] = Data[k, j] - Data[colP[i], j];
+          for (var j = 0; j < dimension; j++) d += buff[j] * buff[j];
+          d = valP[i] / d;
+
+          // Sum positive force
+          for (var j = 0; j < dimension; j++) posF[k, j] += d * buff[j];
+        }
+      }
+    }
+
+    #region Helpers
+    private void Fill(int n) {
+      for (var i = 0; i < n; i++) Insert(i);
+    }
+    private void Init(SpacePartitioningTree p, double[,] inpData, IEnumerable<double> inpCorner, IEnumerable<double> inpWidth) {
+      parent = p;
+      dimension = inpData.GetLength(1);
+      noChildren = 2;
+      for (uint i = 1; i < dimension; i++) noChildren *= 2;
+      Data = inpData;
+      isLeaf = true;
+      size = 0;
+      cumulativeSize = 0;
+      boundary = new Cell((uint)dimension);
+      inpCorner.ForEach((i, x) => boundary.SetCorner(i, x));
+      inpWidth.ForEach((i, x) => boundary.SetWidth(i, x));
+
+      children = new SpacePartitioningTree[noChildren];
+      centerOfMass = new double[dimension];
+      buff = new double[dimension];
+
+    }
+    #endregion
+
+  }
+}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNE.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNE.cs	(revision 14784)
+++ 	(revision )
@@ -1,282 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Threading;
-using HeuristicLab.Analysis;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Encodings.RealVectorEncoding;
-using HeuristicLab.Optimization;
-using HeuristicLab.Parameters;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Problems.DataAnalysis;
-using HeuristicLab.Random;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  /// <summary>
-  /// t-distributed stochastic neighbourhood embedding (TSNE) projects the data in a low dimensional 
-  /// space to allow visual cluster identification.
-  /// </summary>
-  [Item("TSNE", "t-distributed stochastic neighbourhood embedding projects the data in a low " +
-                "dimensional space to allow visual cluster identification.")]
-  [Creatable(CreatableAttribute.Categories.DataAnalysis, Priority = 100)]
-  [StorableClass]
-  public sealed class TSNEAnalysis : BasicAlgorithm {
-    public override bool SupportsPause {
-      get { return false; }
-    }
-    public override Type ProblemType {
-      get { return typeof(IDataAnalysisProblem); }
-    }
-    public new IDataAnalysisProblem Problem {
-      get { return (IDataAnalysisProblem)base.Problem; }
-      set { base.Problem = value; }
-    }
-
-    #region Parameternames
-    private const string DistanceParameterName = "DistanceFunction";
-    private const string PerplexityParameterName = "Perplexity";
-    private const string ThetaParameterName = "Theta";
-    private const string NewDimensionsParameterName = "Dimensions";
-    private const string MaxIterationsParameterName = "MaxIterations";
-    private const string StopLyingIterationParameterName = "StopLyingIteration";
-    private const string MomentumSwitchIterationParameterName = "MomentumSwitchIteration";
-    private const string InitialMomentumParameterName = "InitialMomentum";
-    private const string FinalMomentumParameterName = "FinalMomentum";
-    private const string EtaParameterName = "Eta";
-    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
-    private const string SeedParameterName = "Seed";
-    private const string ClassesParameterName = "ClassNames";
-    private const string NormalizationParameterName = "Normalization";
-    #endregion
-
-    #region Parameterproperties
-    public IFixedValueParameter<DoubleValue> PerplexityParameter {
-      get { return Parameters[PerplexityParameterName] as IFixedValueParameter<DoubleValue>; }
-    }
-    public OptionalValueParameter<DoubleValue> ThetaParameter {
-      get { return Parameters[ThetaParameterName] as OptionalValueParameter<DoubleValue>; }
-    }
-    public IFixedValueParameter<IntValue> NewDimensionsParameter {
-      get { return Parameters[NewDimensionsParameterName] as IFixedValueParameter<IntValue>; }
-    }
-    public IValueParameter<IDistance<RealVector>> DistanceParameter {
-      get { return Parameters[DistanceParameterName] as IValueParameter<IDistance<RealVector>>; }
-    }
-    public IFixedValueParameter<IntValue> MaxIterationsParameter {
-      get { return Parameters[MaxIterationsParameterName] as IFixedValueParameter<IntValue>; }
-    }
-    public IFixedValueParameter<IntValue> StopLyingIterationParameter {
-      get { return Parameters[StopLyingIterationParameterName] as IFixedValueParameter<IntValue>; }
-    }
-    public IFixedValueParameter<IntValue> MomentumSwitchIterationParameter {
-      get { return Parameters[MomentumSwitchIterationParameterName] as IFixedValueParameter<IntValue>; }
-    }
-    public IFixedValueParameter<DoubleValue> InitialMomentumParameter {
-      get { return Parameters[InitialMomentumParameterName] as IFixedValueParameter<DoubleValue>; }
-    }
-    public IFixedValueParameter<DoubleValue> FinalMomentumParameter {
-      get { return Parameters[FinalMomentumParameterName] as IFixedValueParameter<DoubleValue>; }
-    }
-    public IFixedValueParameter<DoubleValue> EtaParameter {
-      get { return Parameters[EtaParameterName] as IFixedValueParameter<DoubleValue>; }
-    }
-    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
-      get { return Parameters[SetSeedRandomlyParameterName] as IFixedValueParameter<BoolValue>; }
-    }
-    public IFixedValueParameter<IntValue> SeedParameter {
-      get { return Parameters[SeedParameterName] as IFixedValueParameter<IntValue>; }
-    }
-    public IFixedValueParameter<StringValue> ClassesParameter {
-      get { return Parameters[ClassesParameterName] as IFixedValueParameter<StringValue>; }
-    }
-    public IFixedValueParameter<BoolValue> NormalizationParameter {
-      get { return Parameters[NormalizationParameterName] as IFixedValueParameter<BoolValue>; }
-    }
-    #endregion
-
-    #region  Properties
-    public IDistance<RealVector> Distance {
-      get { return DistanceParameter.Value; }
-    }
-    public double Perplexity {
-      get { return PerplexityParameter.Value.Value; }
-    }
-    public double Theta {
-      get { return ThetaParameter.Value == null ? 0 : ThetaParameter.Value.Value; }
-    }
-    public int NewDimensions {
-      get { return NewDimensionsParameter.Value.Value; }
-    }
-    public int MaxIterations {
-      get { return MaxIterationsParameter.Value.Value; }
-    }
-    public int StopLyingIteration {
-      get { return StopLyingIterationParameter.Value.Value; }
-    }
-    public int MomentumSwitchIteration {
-      get { return MomentumSwitchIterationParameter.Value.Value; }
-    }
-    public double InitialMomentum {
-      get { return InitialMomentumParameter.Value.Value; }
-    }
-    public double FinalMomentum {
-      get { return FinalMomentumParameter.Value.Value; }
-    }
-    public double Eta {
-      get {
-        return EtaParameter.Value == null ? 0 : EtaParameter.Value.Value;
-      }
-    }
-    public bool SetSeedRandomly {
-      get { return SetSeedRandomlyParameter.Value.Value; }
-    }
-    public uint Seed {
-      get { return (uint)SeedParameter.Value.Value; }
-    }
-    public string Classes {
-      get { return ClassesParameter.Value.Value; }
-    }
-    public bool Normalization {
-      get { return NormalizationParameter.Value.Value; }
-    }
-    [Storable]
-    public TSNE<RealVector> tsne;
-    #endregion
-
-    #region Constructors & Cloning
-    [StorableConstructor]
-    private TSNEAnalysis(bool deserializing) : base(deserializing) { }
-    private TSNEAnalysis(TSNEAnalysis original, Cloner cloner) : base(original, cloner) { }
-    public override IDeepCloneable Clone(Cloner cloner) { return new TSNEAnalysis(this, cloner); }
-    public TSNEAnalysis() {
-      Problem = new RegressionProblem();
-      Parameters.Add(new ValueParameter<IDistance<RealVector>>(DistanceParameterName, "The distance function used to differentiate similar from non-similar points", new EuclideanDistance()));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(PerplexityParameterName, "Perplexity-Parameter of TSNE. Comparable to k in a k-nearest neighbour algorithm. Recommended Value is Floor(number of points /3) or lower", new DoubleValue(25)));
-      Parameters.Add(new OptionalValueParameter<DoubleValue>(ThetaParameterName, "Value describing how much appoximated gradients my differ from exact gradients. Set to 0 for exact calculation and in [0,1] otherwise \n CAUTION: exact calculation of forces requires building a non-sparse N*N matrix where N is the number of data points\n This may exceed memory limitations", new DoubleValue(0.1)));
-      Parameters.Add(new FixedValueParameter<IntValue>(NewDimensionsParameterName, "Dimensionality of projected space (usually 2 for easy visual analysis", new IntValue(2)));
-      Parameters.Add(new FixedValueParameter<IntValue>(MaxIterationsParameterName, "Maximum number of iterations for gradient descent", new IntValue(1000)));
-      Parameters.Add(new FixedValueParameter<IntValue>(StopLyingIterationParameterName, "Number of iterations after which p is no longer approximated", new IntValue(0)));
-      Parameters.Add(new FixedValueParameter<IntValue>(MomentumSwitchIterationParameterName, "Number of iterations after which the momentum in the gradient descent is switched", new IntValue(0)));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(InitialMomentumParameterName, "The initial momentum in the gradient descent", new DoubleValue(0.5)));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(FinalMomentumParameterName, "The final momentum", new DoubleValue(0.8)));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(EtaParameterName, "Gradient Descent learning rate", new DoubleValue(200)));
-      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "If the seed should be random", new BoolValue(true)));
-      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The seed used if it should not be random", new IntValue(0)));
-      Parameters.Add(new FixedValueParameter<StringValue>(ClassesParameterName, "name of the column specifying the class lables of each data point. \n if the lable column can not be found Training/Test is used as labels", new StringValue("none")));
-      Parameters.Add(new FixedValueParameter<BoolValue>(NormalizationParameterName, "Wether the data should be zero centered and have variance of 1 for each variable, so different scalings are ignored", new BoolValue(true)));
-
-      MomentumSwitchIterationParameter.Hidden = true;
-      InitialMomentumParameter.Hidden = true;
-      FinalMomentumParameter.Hidden = true;
-      StopLyingIterationParameter.Hidden = true;
-      EtaParameter.Hidden = true;
-    }
-    #endregion
-
-    public override void Stop() {
-      base.Stop();
-      if(tsne != null) tsne.Running = false;
-    }
-
-    protected override void Run(CancellationToken cancellationToken) {
-      var dataRowNames = new Dictionary<string, List<int>>();
-      var rows = new Dictionary<string, ScatterPlotDataRow>();
-      var problemData = Problem.ProblemData;
-
-      //color datapoints acording to Classes-Variable (be it double or string)
-      if(problemData.Dataset.VariableNames.Contains(Classes)) {
-        if((problemData.Dataset as Dataset).VariableHasType<string>(Classes)) {
-          var classes = problemData.Dataset.GetStringValues(Classes).ToArray();
-          for(var i = 0; i < classes.Length; i++) {
-            if(!dataRowNames.ContainsKey(classes[i])) dataRowNames.Add(classes[i], new List<int>());
-            dataRowNames[classes[i]].Add(i);
-          }
-        } else if((problemData.Dataset as Dataset).VariableHasType<double>(Classes)) {
-          var classValues = problemData.Dataset.GetDoubleValues(Classes).ToArray();
-          var max = classValues.Max() + 0.1;
-          var min = classValues.Min() - 0.1;
-          const int contours = 8;
-          for(var i = 0; i < contours; i++) {
-            var contourname = GetContourName(i, min, max, contours);
-            dataRowNames.Add(contourname, new List<int>());
-            rows.Add(contourname, new ScatterPlotDataRow(contourname, "", new List<Point2D<double>>()));
-            rows[contourname].VisualProperties.Color = GetHeatMapColor(i, contours);
-            rows[contourname].VisualProperties.PointSize = i + 3;
-          }
-          for(var i = 0; i < classValues.Length; i++) {
-            dataRowNames[GetContourName(classValues[i], min, max, contours)].Add(i);
-          }
-        }
-      } else {
-        dataRowNames.Add("Training", problemData.TrainingIndices.ToList());
-        dataRowNames.Add("Test", problemData.TestIndices.ToList());
-      }
-
-      //Set up and run TSNE
-      if(SetSeedRandomly) SeedParameter.Value.Value = new System.Random().Next();
-      var random = new MersenneTwister(Seed);
-      tsne = new TSNE<RealVector>(Distance, random, Results, MaxIterations, StopLyingIteration, MomentumSwitchIteration, InitialMomentum, FinalMomentum, Eta, dataRowNames, rows);
-      var dataset = problemData.Dataset;
-      var allowedInputVariables = problemData.AllowedInputVariables.ToArray();
-      var data = new RealVector[dataset.Rows];
-      for(var row = 0; row < dataset.Rows; row++) data[row] = new RealVector(allowedInputVariables.Select(col => dataset.GetDoubleValue(col, row)).ToArray());
-      if(Normalization) data = NormalizeData(data);
-      tsne.Run(data, NewDimensions, Perplexity, Theta);
-    }
-
-    private static RealVector[] NormalizeData(IReadOnlyList<RealVector> data) {
-      var n = data[0].Length;
-      var mean = new double[n];
-      var sd = new double[n];
-      var nData = new RealVector[data.Count];
-      for(var i = 0; i < n; i++) {
-        var i1 = i;
-        sd[i] = Enumerable.Range(0, data.Count).Select(x => data[x][i1]).StandardDeviation();
-        mean[i] = Enumerable.Range(0, data.Count).Select(x => data[x][i1]).Average();
-      }
-      for(var i = 0; i < data.Count; i++) {
-        nData[i] = new RealVector(n);
-        for(var j = 0; j < n; j++) nData[i][j] = (data[i][j] - mean[j]) / sd[j];
-      }
-      return nData;
-    }
-    private static Color GetHeatMapColor(int contourNr, int noContours) {
-      var q = (double)contourNr / noContours;  // q in [0,1]
-      var c = q < 0.5 ? Color.FromArgb((int)(q * 2 * 255), 255, 0) : Color.FromArgb(255, (int)((1 - q) * 2 * 255), 0);
-      return c;
-    }
-    private static string GetContourName(double value, double min, double max, int noContours) {
-      var size = (max - min) / noContours;
-      var contourNr = (int)((value - min) / size);
-      return GetContourName(contourNr, min, max, noContours);
-    }
-    private static string GetContourName(int i, double min, double max, int noContours) {
-      var size = (max - min) / noContours;
-      return "[" + (min + i * size) + ";" + (min + (i + 1) * size) + ")";
-    }
-  }
-}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs	(revision 14785)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs	(revision 14785)
@@ -0,0 +1,293 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.RealVectorEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// t-distributed stochastic neighbourhood embedding (tSNE) projects the data in a low dimensional 
+  /// space to allow visual cluster identification.
+  /// </summary>
+  [Item("tSNE", "t-distributed stochastic neighbourhood embedding projects the data in a low " +
+                "dimensional space to allow visual cluster identification.")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysis, Priority = 100)]
+  [StorableClass]
+  public sealed class TSNEAlgorithm : BasicAlgorithm {
+    public override bool SupportsPause {
+      get { return false; }
+    }
+    public override Type ProblemType {
+      get { return typeof(IDataAnalysisProblem); }
+    }
+    public new IDataAnalysisProblem Problem {
+      get { return (IDataAnalysisProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    #region parameter names
+    private const string DistanceParameterName = "DistanceFunction";
+    private const string PerplexityParameterName = "Perplexity";
+    private const string ThetaParameterName = "Theta";
+    private const string NewDimensionsParameterName = "Dimensions";
+    private const string MaxIterationsParameterName = "MaxIterations";
+    private const string StopLyingIterationParameterName = "StopLyingIteration";
+    private const string MomentumSwitchIterationParameterName = "MomentumSwitchIteration";
+    private const string InitialMomentumParameterName = "InitialMomentum";
+    private const string FinalMomentumParameterName = "FinalMomentum";
+    private const string EtaParameterName = "Eta";
+    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
+    private const string SeedParameterName = "Seed";
+    private const string ClassesParameterName = "ClassNames";
+    private const string NormalizationParameterName = "Normalization";
+    #endregion
+
+    #region parameter properties
+    public IFixedValueParameter<DoubleValue> PerplexityParameter {
+      get { return Parameters[PerplexityParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    public IFixedValueParameter<DoubleValue> ThetaParameter {
+      get { return Parameters[ThetaParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    public IFixedValueParameter<IntValue> NewDimensionsParameter {
+      get { return Parameters[NewDimensionsParameterName] as IFixedValueParameter<IntValue>; }
+    }
+    public IValueParameter<IDistance<double[]>> DistanceParameter {
+      get { return Parameters[DistanceParameterName] as IValueParameter<IDistance<double[]>>; }
+    }
+    public IFixedValueParameter<IntValue> MaxIterationsParameter {
+      get { return Parameters[MaxIterationsParameterName] as IFixedValueParameter<IntValue>; }
+    }
+    public IFixedValueParameter<IntValue> StopLyingIterationParameter {
+      get { return Parameters[StopLyingIterationParameterName] as IFixedValueParameter<IntValue>; }
+    }
+    public IFixedValueParameter<IntValue> MomentumSwitchIterationParameter {
+      get { return Parameters[MomentumSwitchIterationParameterName] as IFixedValueParameter<IntValue>; }
+    }
+    public IFixedValueParameter<DoubleValue> InitialMomentumParameter {
+      get { return Parameters[InitialMomentumParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    public IFixedValueParameter<DoubleValue> FinalMomentumParameter {
+      get { return Parameters[FinalMomentumParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    public IFixedValueParameter<DoubleValue> EtaParameter {
+      get { return Parameters[EtaParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return Parameters[SetSeedRandomlyParameterName] as IFixedValueParameter<BoolValue>; }
+    }
+    public IFixedValueParameter<IntValue> SeedParameter {
+      get { return Parameters[SeedParameterName] as IFixedValueParameter<IntValue>; }
+    }
+    public IFixedValueParameter<StringValue> ClassesParameter {
+      get { return Parameters[ClassesParameterName] as IFixedValueParameter<StringValue>; }
+    }
+    public IFixedValueParameter<BoolValue> NormalizationParameter {
+      get { return Parameters[NormalizationParameterName] as IFixedValueParameter<BoolValue>; }
+    }
+    #endregion
+
+    #region  Properties
+    public IDistance<double[]> Distance {
+      get { return DistanceParameter.Value; }
+    }
+    public double Perplexity {
+      get { return PerplexityParameter.Value.Value; }
+      set { PerplexityParameter.Value.Value = value; }
+    }
+    public double Theta {
+      get { return ThetaParameter.Value.Value; }
+      set { ThetaParameter.Value.Value = value; }
+    }
+    public int NewDimensions {
+      get { return NewDimensionsParameter.Value.Value; }
+      set { NewDimensionsParameter.Value.Value = value; }
+    }
+    public int MaxIterations {
+      get { return MaxIterationsParameter.Value.Value; }
+      set { MaxIterationsParameter.Value.Value = value; }
+    }
+    public int StopLyingIteration {
+      get { return StopLyingIterationParameter.Value.Value; }
+      set { StopLyingIterationParameter.Value.Value = value; }
+    }
+    public int MomentumSwitchIteration {
+      get { return MomentumSwitchIterationParameter.Value.Value; }
+      set { MomentumSwitchIterationParameter.Value.Value = value; }
+    }
+    public double InitialMomentum {
+      get { return InitialMomentumParameter.Value.Value; }
+      set { InitialMomentumParameter.Value.Value = value; }
+    }
+    public double FinalMomentum {
+      get { return FinalMomentumParameter.Value.Value; }
+      set { FinalMomentumParameter.Value.Value = value; }
+    }
+    public double Eta {
+      get { return EtaParameter.Value.Value; }
+      set { EtaParameter.Value.Value = value; }
+    }
+    public bool SetSeedRandomly {
+      get { return SetSeedRandomlyParameter.Value.Value; }
+      set { SetSeedRandomlyParameter.Value.Value = value; }
+    }
+    public int Seed {
+      get { return SeedParameter.Value.Value; }
+      set { SeedParameter.Value.Value = value; }
+    }
+    public string Classes {
+      get { return ClassesParameter.Value.Value; }
+      set { ClassesParameter.Value.Value = value; }
+    }
+    public bool Normalization {
+      get { return NormalizationParameter.Value.Value; }
+      set { NormalizationParameter.Value.Value = value; }
+    }
+    [Storable]
+    public TSNE<double[]> tsne;
+    #endregion
+
+    #region Constructors & Cloning
+    [StorableConstructor]
+    private TSNEAlgorithm(bool deserializing) : base(deserializing) { }
+    private TSNEAlgorithm(TSNEAlgorithm original, Cloner cloner) : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) { return new TSNEAlgorithm(this, cloner); }
+    public TSNEAlgorithm() {
+      Problem = new RegressionProblem();
+      Parameters.Add(new ValueParameter<IDistance<double[]>>(DistanceParameterName, "The distance function used to differentiate similar from non-similar points", new EuclideanDistance()));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(PerplexityParameterName, "Perplexity-Parameter of tSNE. Comparable to k in a k-nearest neighbour algorithm. Recommended value is floor(number of points /3) or lower", new DoubleValue(25)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(ThetaParameterName, "Value describing how much appoximated gradients my differ from exact gradients. Set to 0 for exact calculation and in [0,1] otherwise \n CAUTION: exact calculation of forces requires building a non-sparse N*N matrix where N is the number of data points\n This may exceed memory limitations", new DoubleValue(0)));
+      Parameters.Add(new FixedValueParameter<IntValue>(NewDimensionsParameterName, "Dimensionality of projected space (usually 2 for easy visual analysis)", new IntValue(2)));
+      Parameters.Add(new FixedValueParameter<IntValue>(MaxIterationsParameterName, "Maximum number of iterations for gradient descent", new IntValue(1000)));
+      Parameters.Add(new FixedValueParameter<IntValue>(StopLyingIterationParameterName, "Number of iterations after which p is no longer approximated", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<IntValue>(MomentumSwitchIterationParameterName, "Number of iterations after which the momentum in the gradient descent is switched", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(InitialMomentumParameterName, "The initial momentum in the gradient descent", new DoubleValue(0.5)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(FinalMomentumParameterName, "The final momentum", new DoubleValue(0.8)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(EtaParameterName, "Gradient descent learning rate", new DoubleValue(200)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "If the seed should be random", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The seed used if it should not be random", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<StringValue>(ClassesParameterName, "name of the column specifying the class lables of each data point. \n if the lable column can not be found training/test is used as labels", new StringValue("none")));
+      Parameters.Add(new FixedValueParameter<BoolValue>(NormalizationParameterName, "Whether the data should be zero centered and have variance of 1 for each variable, so different scalings are ignored", new BoolValue(true)));
+
+      MomentumSwitchIterationParameter.Hidden = true;
+      InitialMomentumParameter.Hidden = true;
+      FinalMomentumParameter.Hidden = true;
+      StopLyingIterationParameter.Hidden = true;
+      EtaParameter.Hidden = true;
+    }
+    #endregion
+
+    public override void Stop() {
+      base.Stop();
+      if (tsne != null) tsne.Running = false;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      var dataRowNames = new Dictionary<string, List<int>>();
+      var rows = new Dictionary<string, ScatterPlotDataRow>();
+      var problemData = Problem.ProblemData;
+
+      //color datapoints acording to classes variable (be it double or string)
+      if (problemData.Dataset.VariableNames.Contains(Classes)) {
+        if ((problemData.Dataset as Dataset).VariableHasType<string>(Classes)) {
+          var classes = problemData.Dataset.GetStringValues(Classes).ToArray();
+          for (var i = 0; i < classes.Length; i++) {
+            if (!dataRowNames.ContainsKey(classes[i])) dataRowNames.Add(classes[i], new List<int>());
+            dataRowNames[classes[i]].Add(i);
+          }
+        } else if ((problemData.Dataset as Dataset).VariableHasType<double>(Classes)) {
+          var classValues = problemData.Dataset.GetDoubleValues(Classes).ToArray();
+          var max = classValues.Max() + 0.1;     // TODO consts
+          var min = classValues.Min() - 0.1;
+          const int contours = 8;
+          for (var i = 0; i < contours; i++) {
+            var contourname = GetContourName(i, min, max, contours);
+            dataRowNames.Add(contourname, new List<int>());
+            rows.Add(contourname, new ScatterPlotDataRow(contourname, "", new List<Point2D<double>>()));
+            rows[contourname].VisualProperties.Color = GetHeatMapColor(i, contours);
+            rows[contourname].VisualProperties.PointSize = i + 3;
+          }
+          for (var i = 0; i < classValues.Length; i++) {
+            dataRowNames[GetContourName(classValues[i], min, max, contours)].Add(i);
+          }
+        }
+      } else {
+        dataRowNames.Add("Training", problemData.TrainingIndices.ToList());
+        dataRowNames.Add("Test", problemData.TestIndices.ToList());
+      }
+
+      // set up and run tSNE
+      if (SetSeedRandomly) Seed = new System.Random().Next();
+      var random = new MersenneTwister((uint)Seed);
+      tsne = new TSNE<double[]>(Distance, random, Results, MaxIterations, StopLyingIteration, MomentumSwitchIteration, InitialMomentum, FinalMomentum, Eta, dataRowNames, rows);
+      var dataset = problemData.Dataset;
+      var allowedInputVariables = problemData.AllowedInputVariables.ToArray();
+      var data = new double[dataset.Rows][];
+      for (var row = 0; row < dataset.Rows; row++) data[row] = allowedInputVariables.Select(col => dataset.GetDoubleValue(col, row)).ToArray();
+      if (Normalization) data = NormalizeData(data);
+      tsne.Run(data, NewDimensions, Perplexity, Theta);
+    }
+
+    private static double[][] NormalizeData(IReadOnlyList<double[]> data) {
+      var n = data[0].Length;
+      var mean = new double[n];
+      var sd = new double[n];
+      var nData = new double[data.Count][];
+      for (var i = 0; i < n; i++) {
+        var i1 = i;
+        sd[i] = Enumerable.Range(0, data.Count).Select(x => data[x][i1]).StandardDeviation();
+        mean[i] = Enumerable.Range(0, data.Count).Select(x => data[x][i1]).Average();
+      }
+      for (var i = 0; i < data.Count; i++) {
+        nData[i] = new double[n];
+        for (var j = 0; j < n; j++) nData[i][j] = (data[i][j] - mean[j]) / sd[j];
+      }
+      return nData;
+    }
+    private static Color GetHeatMapColor(int contourNr, int noContours) {
+      var q = (double)contourNr / noContours;  // q in [0,1]
+      var c = q < 0.5 ? Color.FromArgb((int)(q * 2 * 255), 255, 0) : Color.FromArgb(255, (int)((1 - q) * 2 * 255), 0);
+      return c;
+    }
+    private static string GetContourName(double value, double min, double max, int noContours) {
+      var size = (max - min) / noContours;
+      var contourNr = (int)((value - min) / size);
+      return GetContourName(contourNr, min, max, noContours);
+    }
+    private static string GetContourName(int i, double min, double max, int noContours) {
+      var size = (max - min) / noContours;
+      return "[" + (min + i * size) + ";" + (min + (i + 1) * size) + ")";
+    }
+  }
+}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs	(revision 14784)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs	(revision 14785)
@@ -58,4 +58,5 @@
 using System.Linq;
 using HeuristicLab.Analysis;
+using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -67,5 +68,5 @@
 namespace HeuristicLab.Algorithms.DataAnalysis {
   [StorableClass]
-  public class TSNE<T> : DeepCloneable where T : class, IDeepCloneable {
+  public class TSNE<T> : DeepCloneable /*where T : class, IDeepCloneable*/ {
 
     private const string IterationResultName = "Iteration";
@@ -101,5 +102,5 @@
 
     #region Stopping 
-    public volatile bool Running;
+    public volatile bool Running;      // TODO
     #endregion
 
@@ -164,10 +165,10 @@
 
       // Initialize solution (randomly)
-      for (var i = 0; i < noDatapoints; i++) for (var j = 0; j < newDimensions; j++) newData[i, j] = rand.NextDouble() * .0001;
+      for (var i = 0; i < noDatapoints; i++) for (var j = 0; j < newDimensions; j++) newData[i, j] = rand.NextDouble() * .0001;  // TODO const
 
       // Perform main training loop
       for (var iter = 0; iter < maxIter && Running; iter++) {
         if (exact) ComputeExactGradient(p, newData, noDatapoints, newDimensions, dY);
-        else ComputeGradient(rowP, colP, valP, newData, noDatapoints, newDimensions, dY, theta);
+        else ComputeApproximateGradient(rowP, colP, valP, newData, noDatapoints, newDimensions, dY, theta);
         // Update gains
         for (var i = 0; i < noDatapoints; i++) for (var j = 0; j < newDimensions; j++) gains[i, j] = Math.Sign(dY[i, j]) != Math.Sign(uY[i, j]) ? gains[i, j] + .2 : gains[i, j] * .8;
@@ -189,7 +190,4 @@
       return newData;
     }
-    public static double[,] Run<TR>(TR[] data, int newDimensions, double perplexity, double theta, IDistance<TR> distance, IRandom random) where TR : class, IDeepCloneable {
-      return new TSNE<TR>(distance, random).Run(data, newDimensions, perplexity, theta);
-    }
 
     #region helpers
@@ -205,9 +203,9 @@
       else ((DoubleValue)results[ErrorResultName].Value).Value = 0;
 
-      if (!results.ContainsKey(ErrorPlotResultName)) results.Add(new Result(ErrorPlotResultName, new DataTable(ErrorPlotResultName, "Development of errors during Gradiant descent")));
-      else results[ErrorPlotResultName].Value = new DataTable(ErrorPlotResultName, "Development of errors during Gradiant descent");
+      if (!results.ContainsKey(ErrorPlotResultName)) results.Add(new Result(ErrorPlotResultName, new DataTable(ErrorPlotResultName, "Development of errors during gradient descent")));
+      else results[ErrorPlotResultName].Value = new DataTable(ErrorPlotResultName, "Development of errors during gradient descent");
 
       var plot = results[ErrorPlotResultName].Value as DataTable;
-      if (plot == null) throw new ArgumentException("could not create/access Error-DataTable in Results-Collection");
+      if (plot == null) throw new ArgumentException("could not create/access error data table in results collection");
 
       if (!plot.Rows.ContainsKey("errors")) plot.Rows.Add(new DataRow("errors"));
@@ -224,6 +222,6 @@
       var errors = plot.Rows["errors"].Values;
       var c = exact
-        ? EvaluateError(p, newData, noDatapoints, newDimensions)
-        : EvaluateError(rowP, colP, valP, newData, theta);
+        ? EvaluateErrorExact(p, newData, noDatapoints, newDimensions)
+        : EvaluateErrorApproximate(rowP, colP, valP, newData, theta);
       errors.Add(c);
       ((IntValue)results[IterationResultName].Value).Value = iter + 1;
@@ -304,18 +302,16 @@
       for (var i = 0; i < n; i++) rowP[i + 1] = rowP[i] + k;
 
+      var objX = new List<IndexedItem<T>>();
+      for (var i = 0; i < n; i++) objX.Add(new IndexedItem<T>(i, x[i]));
+
       // Build ball tree on data set
-      var tree = new VPTree<IDataPoint<T>>(new DataPointDistance<T>(distance));
-      var objX = new List<IDataPoint<T>>();
-      for (var i = 0; i < n; i++) objX.Add(new DataPoint<T>(i, x[i]));
-      tree.Create(objX);
+      var tree = new VantagePointTree<IndexedItem<T>>(new IndexedItemDistance<T>(distance), objX);           // do we really want to re-create the tree on each call?
 
       // Loop over all points to find nearest neighbors
-      var indices = new List<IDataPoint<T>>();
-      var distances = new List<double>();
       for (var i = 0; i < n; i++) {
+        IList<IndexedItem<T>> indices;
+        IList<double> distances;
 
         // Find nearest neighbors
-        indices.Clear();
-        distances.Clear();
         tree.Search(objX[i], k + 1, out indices, out distances);
 
@@ -323,7 +319,7 @@
         var found = false;
         var beta = 1.0;
-        var minBeta = -double.MaxValue;
+        var minBeta = double.MinValue;
         var maxBeta = double.MaxValue;
-        const double tol = 1e-5;
+        const double tol = 1e-5;  // TODO: why 1e-5?
 
         // Iterate until we found a good perplexity
@@ -374,8 +370,8 @@
     }
     private void ComputeGaussianPerplexity(T[] x, int n, double[,] p, double perplexity) {
-      // Compute the squared Euclidean distance matrix
+      // Compute the distance matrix
       var dd = ComputeDistances(x);
+
       // Compute the Gaussian kernel row by row
-
       for (var i = 0; i < n; i++) {
         // Initialize some variables
@@ -389,5 +385,5 @@
         // Iterate until we found a good perplexity
         var iter = 0;
-        while (!found && iter < 200) {
+        while (!found && iter < 200) {       // TODO constant
 
           // Compute Gaussian kernel row
@@ -430,7 +426,9 @@
       }
     }
+
     private double[][] ComputeDistances(T[] x) {
       return x.Select(m => x.Select(n => distance.Get(m, n)).ToArray()).ToArray();
     }
+
     private static void ComputeExactGradient(double[,] p, double[,] y, int n, int d, double[,] dC) {
 
@@ -487,6 +485,6 @@
       }
     }
-    private static void ComputeGradient(int[] rowP, int[] colP, double[] valP, double[,] y, int n, int d, double[,] dC, double theta) {
-      var tree = new SPTree(y);
+    private static void ComputeApproximateGradient(int[] rowP, int[] colP, double[] valP, double[,] y, int n, int d, double[,] dC, double theta) {
+      var tree = new SpacePartitioningTree(y);
       double[] sumQ = { 0 };
       var posF = new double[n, d];
@@ -502,8 +500,9 @@
       for (var i = 0; i < n; i++)
         for (var j = 0; j < d; j++) {
-          dC[i, j] = posF[i, j] - negF[i, j] / sumQ[0];
-        }
-    }
-    private static double EvaluateError(double[,] p, double[,] y, int n, int d) {
+          dC[i, j] = (posF[i, j] - negF[i, j]) / sumQ[0]; // TODO: check parenthesis
+        }
+    }
+
+    private static double EvaluateErrorExact(double[,] p, double[,] y, int n, int d) {
       // Compute the squared Euclidean distance matrix
       var dd = new double[n, n];
@@ -531,9 +530,9 @@
       return c;
     }
-    private static double EvaluateError(IReadOnlyList<int> rowP, IReadOnlyList<int> colP, IReadOnlyList<double> valP, double[,] y, double theta) {
+    private static double EvaluateErrorApproximate(IReadOnlyList<int> rowP, IReadOnlyList<int> colP, IReadOnlyList<double> valP, double[,] y, double theta) {
       // Get estimate of normalization term
       var n = y.GetLength(0);
       var d = y.GetLength(1);
-      var tree = new SPTree(y);
+      var tree = new SpacePartitioningTree(y);
       var buff = new double[d];
       double[] sumQ = { 0 };
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VPTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VPTree.cs	(revision 14784)
+++ 	(revision )
@@ -1,231 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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/>.
- */
-
-//Code is based on an implementation from Laurens van der Maaten
-
-/*
-*
-* Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-*    must display the following acknowledgement:
-*    This product includes software developed by the Delft University of Technology.
-* 4. Neither the name of the Delft University of Technology nor the names of
-*    its contributors may be used to endorse or promote products derived from
-*    this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS
-* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-* EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-* OF SUCH DAMAGE.
-*
-*/
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Random;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  /// <summary>
-  /// Vantage point tree  (or VP tree) is a metric tree that segregates data in a metric space by choosing 
-  /// a position in the space (the "vantage point") and partitioning the data points into two parts: 
-  /// those points that are nearer to the vantage point than a threshold, and those points that are not. 
-  /// By recursively applying this procedure to partition the data into smaller and smaller sets, a tree 
-  /// data structure is created where neighbors in the tree are likely to be neighbors in the space.
-  /// </summary>
-  /// <typeparam name="T"></typeparam>
-  [StorableClass]
-  public class VPTree<T> : DeepCloneable, IVPTree<T> where T : class, IDeepCloneable {
-    #region properties
-    [Storable]
-    private List<T> items;
-    [Storable]
-    private double tau;
-    [Storable]
-    private Node root;
-    [Storable]
-    private IDistance<T> distance;
-    #endregion
-
-    #region HLConstructors & Cloning
-    [StorableConstructor]
-    protected VPTree(bool deserializing) { }
-    protected VPTree(VPTree<T> original, Cloner cloner)
-      : base(original, cloner) {
-      items = original.items.Select(cloner.Clone).ToList();
-      tau = original.tau;
-      root = cloner.Clone(original.root);
-      distance = cloner.Clone(distance);
-    }
-    public override IDeepCloneable Clone(Cloner cloner) { return new VPTree<T>(this, cloner); }
-    public VPTree(IDistance<T> distance) {
-      root = null;
-      this.distance = distance;
-    }
-    #endregion
-
-    public void Create(IEnumerable<T> items) {
-      this.items = items.Select(x => x).ToList();
-      root = BuildFromPoints(0, this.items.Count);
-    }
-
-    public void Search(T target, int k, out List<T> results, out List<double> distances) {
-      var heap = new PriorityQueue<double, HeapItem>(double.MaxValue, double.MinValue, k);
-      tau = double.MaxValue;
-      Search(root, target, k, heap);
-      results = new List<T>();
-      distances = new List<double>();
-      while (heap.Size > 0) {
-        results.Add(items[heap.PeekMinValue().Index]);
-        distances.Add(heap.PeekMinValue().Dist);
-        heap.RemoveMin();
-      }
-      results.Reverse();
-      distances.Reverse();
-    }
-
-    private Node BuildFromPoints(int lower, int upper) {
-      if (upper == lower)      // indicates that we're done here!
-        return null;
-
-      // Lower index is center of current node
-      var node = new Node { index = lower };
-      var r = new MersenneTwister(); //outer behaviour does not change with the random seed => no need to take the IRandom from the algorithm 
-      if (upper - lower <= 1) return node; // if we did not arrive at leaf yet
-
-      // Choose an arbitrary point and move it to the start
-      var i = (int)(r.NextDouble() / 1 * (upper - lower - 1)) + lower;
-      items.Swap(lower, i);
-
-      // Partition around the median distance
-      var median = (upper + lower) / 2;
-      items.NthElement(lower + 1, upper - 1, median, distance.GetDistanceComparer(items[lower]));
-
-      // Threshold of the new node will be the distance to the median
-      node.threshold = distance.Get(items[lower], items[median]);
-
-      // Recursively build tree
-      node.index = lower;
-      node.left = BuildFromPoints(lower + 1, median);
-      node.right = BuildFromPoints(median, upper);
-
-      // Return result
-      return node;
-    }
-
-    private void Search(Node node, T target, int k, PriorityQueue<double, HeapItem> heap) {
-      if (node == null) return;
-      var dist = distance.Get(items[node.index], target);
-      if (dist < tau) {
-        if (heap.Size == k) heap.RemoveMin();
-        heap.Insert(-dist, new HeapItem(node.index, dist));//TODO check if minheap or maxheap should be used here
-        if (heap.Size == k) tau = heap.PeekMinValue().Dist;
-      }
-      if (node.left == null && node.right == null) return;
-
-      if (dist < node.threshold) {
-        if (dist - tau <= node.threshold) Search(node.left, target, k, heap);   // if there can still be neighbors inside the ball, recursively search left child first
-        if (dist + tau >= node.threshold) Search(node.right, target, k, heap);  // if there can still be neighbors outside the ball, recursively search right child
-      } else {
-        if (dist + tau >= node.threshold) Search(node.right, target, k, heap);  // if there can still be neighbors outside the ball, recursively search right child first
-        if (dist - tau <= node.threshold) Search(node.left, target, k, heap);   // if there can still be neighbors inside the ball, recursively search left child
-      }
-
-    }
-
-    [StorableClass]
-    private sealed class Node : Item {
-      [Storable]
-      public int index;
-      [Storable]
-      public double threshold;
-      [Storable]
-      public Node left;
-      [Storable]
-      public Node right;
-
-      #region HLConstructors & Cloning
-      [StorableConstructor]
-      private Node(bool deserializing) : base(deserializing) { }
-      private Node(Node original, Cloner cloner) : base(original, cloner) {
-        index = original.index;
-        threshold = original.threshold;
-        left = (Node)original.left.Clone(cloner);
-        right = (Node)original.right.Clone(cloner);
-      }
-      internal Node() {
-        index = 0;
-        threshold = 0;
-        left = null;
-        right = null;
-      }
-      public override IDeepCloneable Clone(Cloner cloner) {
-        return new Node(this, cloner);
-      }
-      #endregion
-    }
-
-    [StorableClass]
-    private sealed class HeapItem : Item, IComparable<HeapItem> {
-      [Storable]
-      public int Index;
-      [Storable]
-      public double Dist;
-
-      #region HLConstructors & Cloning
-      [StorableConstructor]
-      private HeapItem(bool deserializing) : base(deserializing) { }
-      private HeapItem(HeapItem original, Cloner cloner)
-      : base(original, cloner) {
-        Index = original.Index;
-        Dist = original.Dist;
-      }
-      public override IDeepCloneable Clone(Cloner cloner) { return new HeapItem(this, cloner); }
-      public HeapItem(int index, double dist) {
-        Index = index;
-        Dist = dist;
-      }
-      #endregion
-
-      public int CompareTo(HeapItem other) {
-        return Dist.CompareTo(Dist);
-      }
-    }
-  }
-}
Index: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VantagePointTree.cs
===================================================================
--- branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VantagePointTree.cs	(revision 14785)
+++ branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VantagePointTree.cs	(revision 14785)
@@ -0,0 +1,167 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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/>.
+ */
+
+//Code is based on an implementation from Laurens van der Maaten
+
+/*
+*
+* Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology)
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+* 3. All advertising materials mentioning features or use of this software
+*    must display the following acknowledgement:
+*    This product includes software developed by the Delft University of Technology.
+* 4. Neither the name of the Delft University of Technology nor the names of
+*    its contributors may be used to endorse or promote products derived from
+*    this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS
+* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+* EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+* OF SUCH DAMAGE.
+*
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Vantage point tree  (or VP tree) is a metric tree that segregates data in a metric space by choosing 
+  /// a position in the space (the "vantage point") and partitioning the data points into two parts: 
+  /// those points that are nearer to the vantage point than a threshold, and those points that are not. 
+  /// By recursively applying this procedure to partition the data into smaller and smaller sets, a tree 
+  /// data structure is created where neighbors in the tree are likely to be neighbors in the space.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [StorableClass]
+  public class VantagePointTree<T> : IVantagePointTree<T> {
+    #region properties
+    private readonly List<T> items;
+    private readonly Node root;
+    private readonly IDistance<T> distance;
+    #endregion
+
+    public VantagePointTree(IDistance<T> distance, IEnumerable<T> items) : base() {
+      root = null;
+      this.distance = distance;
+      this.items = items.Select(x => x).ToList();
+      root = BuildFromPoints(0, this.items.Count);
+    }
+
+    public void Search(T target, int k, out IList<T> results, out IList<double> distances) {
+      var heap = new PriorityQueue<double, IndexedItem<double>>(double.MaxValue, double.MinValue, k);
+      Search(root, target, k, heap, double.MaxValue);
+      var res = new List<T>();
+      var dist = new List<double>();
+      while (heap.Size > 0) {
+        res.Add(items[heap.PeekMinValue().Index]);
+        dist.Add(heap.PeekMinValue().Value);
+        heap.RemoveMin();
+      }
+      res.Reverse();
+      dist.Reverse();
+      results = res;
+      distances = dist;
+    }
+
+    private void Search(Node node, T target, int k, PriorityQueue<double, IndexedItem<double>> heap, double tau = double.MaxValue) {
+      if (node == null) return;
+      var dist = distance.Get(items[node.index], target);
+      if (dist < tau) {
+        if (heap.Size == k) heap.RemoveMin();
+        heap.Insert(-dist, new IndexedItem<double>(node.index, dist));//TODO check if minheap or maxheap should be used here
+        if (heap.Size == k) tau = heap.PeekMinValue().Value;
+      }
+      if (node.left == null && node.right == null) return;
+
+      if (dist < node.threshold) {
+        if (dist - tau <= node.threshold) Search(node.left, target, k, heap, tau);   // if there can still be neighbors inside the ball, recursively search left child first
+        if (dist + tau >= node.threshold) Search(node.right, target, k, heap, tau);  // if there can still be neighbors outside the ball, recursively search right child
+      } else {
+        if (dist + tau >= node.threshold) Search(node.right, target, k, heap, tau);  // if there can still be neighbors outside the ball, recursively search right child first
+        if (dist - tau <= node.threshold) Search(node.left, target, k, heap, tau);   // if there can still be neighbors inside the ball, recursively search left child
+      }
+    }
+
+    private Node BuildFromPoints(int lower, int upper) {
+      if (upper == lower)      // indicates that we're done here!
+        return null;
+
+      // Lower index is center of current node
+      var node = new Node { index = lower };
+      var r = new MersenneTwister(); //outer behaviour does not change with the random seed => no need to take the IRandom from the algorithm 
+      if (upper - lower <= 1) return node; // if we did not arrive at leaf yet
+
+      // Choose an arbitrary point and move it to the start
+      var i = (int)(r.NextDouble() / 1 * (upper - lower - 1)) + lower;
+      items.Swap(lower, i);
+
+      // Partition around the median distance
+      var median = (upper + lower) / 2;
+      items.NthElement(lower + 1, upper - 1, median, distance.GetDistanceComparer(items[lower]));
+
+      // Threshold of the new node will be the distance to the median
+      node.threshold = distance.Get(items[lower], items[median]);
+
+      // Recursively build tree
+      node.index = lower;
+      node.left = BuildFromPoints(lower + 1, median);
+      node.right = BuildFromPoints(median, upper);
+
+      // Return result
+      return node;
+    }
+
+    private sealed class Node {
+      public int index;
+      public double threshold;
+      public Node left;
+      public Node right;
+
+      internal Node() {
+        index = 0;
+        threshold = 0;
+        left = null;
+        right = null;
+      }
+    }
+  }
+}
