Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/FixedDataAnalysisAlgorithm.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/FixedDataAnalysisAlgorithm.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/FixedDataAnalysisAlgorithm.cs	(revision 15532)
@@ -30,5 +30,5 @@
 namespace HeuristicLab.Algorithms.DataAnalysis {
   [StorableClass]
-  public abstract class FixedDataAnalysisAlgorithm<T> : BasicAlgorithm where T : class, IDataAnalysisProblem {
+  public abstract class FixedDataAnalysisAlgorithm<T> : BasicAlgorithm, IDataAnalysisAlgorithm<T> where T : class, IDataAnalysisProblem {
     #region Properties
     public override Type ProblemType {
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessRegression.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessRegression.cs	(revision 15532)
@@ -39,5 +39,5 @@
   [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 160)]
   [StorableClass]
-  public sealed class GaussianProcessRegression : GaussianProcessBase, IStorableContent {
+  public sealed class GaussianProcessRegression : GaussianProcessBase, IStorableContent, IDataAnalysisAlgorithm<IRegressionProblem> {
     public string Filename { get; set; }
 
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 15532)
@@ -320,4 +320,5 @@
     <Compile Include="TSNE\Distances\IndexedItemDistance.cs" />
     <Compile Include="TSNE\Distances\ManhattanDistance.cs" />
+	<Compile Include="TSNE\Distances\WeightedEuclideanDistance.cs" />
     <Compile Include="TSNE\Distances\IDistance.cs" />
     <Compile Include="TSNE\PriorityQueue.cs" />
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegression.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegression.cs	(revision 15532)
@@ -36,5 +36,5 @@
   [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 100)]
   [StorableClass]
-  public sealed class KernelRidgeRegression : BasicAlgorithm {
+  public sealed class KernelRidgeRegression : BasicAlgorithm, IDataAnalysisAlgorithm<IRegressionProblem> {
     private const string SolutionResultName = "Kernel ridge regression solution";
 
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/CosineDistance.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/CosineDistance.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/CosineDistance.cs	(revision 15532)
@@ -22,5 +22,4 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -28,5 +27,4 @@
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
-
   /// <summary>
   /// The angular distance as defined as a normalized distance measure dependent on the angle between two vectors.
@@ -35,5 +33,4 @@
   [Item("CosineDistance", "The angular distance as defined as a normalized distance measure dependent on the angle between two vectors.")]
   public class CosineDistance : DistanceBase<IEnumerable<double>> {
-
     #region HLConstructors & Cloning
     [StorableConstructor]
@@ -48,23 +45,24 @@
 
     #region statics
-    public static double GetDistance(IReadOnlyList<double> point1, IReadOnlyList<double> point2) {
-      if (point1.Count != point2.Count) throw new ArgumentException("Cosine distance not defined on vectors of different length");
-      var innerprod = 0.0;
-      var length1 = 0.0;
-      var length2 = 0.0;
-
-      for (var i = 0; i < point1.Count; i++) {
-        double d1 = point1[i], d2 = point2[i];
-        innerprod += d1 * d2;
-        length1 += d1 * d1;
-        length2 += d2 * d2;
+    public static double GetDistance(IEnumerable<double> point1, IEnumerable<double> point2) {
+      using (IEnumerator<double> p1Enum = point1.GetEnumerator(), p2Enum = point2.GetEnumerator()) {
+        var innerprod = 0.0;
+        var length1 = 0.0;
+        var length2 = 0.0;
+        while (p1Enum.MoveNext() & p2Enum.MoveNext()) {
+          double d1 = p1Enum.Current, d2 = p2Enum.Current;
+          innerprod += d1 * d2;
+          length1 += d1 * d1;
+          length2 += d2 * d2;
+        }
+        var divisor = Math.Sqrt(length1 * length2);
+        if (divisor.IsAlmost(0)) throw new ArgumentException("Cosine distance is not defined on vectors of length 0");
+        if (p1Enum.MoveNext() || p2Enum.MoveNext()) throw new ArgumentException("Cosine distance not defined on vectors of different length");
+        return 1 - innerprod / divisor;
       }
-      var l = Math.Sqrt(length1 * length2);
-      if (l.IsAlmost(0)) throw new ArgumentException("Cosine distance is not defined on vectors of length 0");
-      return 1 - innerprod / l;
     }
     #endregion
     public override double Get(IEnumerable<double> a, IEnumerable<double> b) {
-      return GetDistance(a.ToArray(), b.ToArray());
+      return GetDistance(a, b);
     }
   }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DistanceBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DistanceBase.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DistanceBase.cs	(revision 15532)
@@ -29,5 +29,4 @@
   [StorableClass]
   public abstract class DistanceBase<T> : Item, IDistance<T> {
-
     #region HLConstructors & Cloning
     [StorableConstructor]
@@ -44,12 +43,12 @@
 
     public double Get(object x, object y) {
-      return Get((T)x, (T)y);
+      return Get((T) x, (T) y);
     }
 
     public IComparer GetDistanceComparer(object item) {
-      return new DistanceComparer((T)item, this);
+      return new DistanceComparer((T) item, this);
     }
 
-    private class DistanceComparer : IComparer<T>, IComparer {
+    internal class DistanceComparer : IComparer<T>, IComparer {
       private readonly T item;
       private readonly IDistance<T> dist;
@@ -65,5 +64,5 @@
 
       public int Compare(object x, object y) {
-        return Compare((T)x, (T)y);
+        return Compare((T) x, (T) y);
       }
     }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/EuclideanDistance.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/EuclideanDistance.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/EuclideanDistance.cs	(revision 15532)
@@ -31,26 +31,28 @@
   [Item("EuclideanDistance", "A norm function that uses Euclidean distance")]
   public class EuclideanDistance : DistanceBase<IEnumerable<double>> {
-
     #region HLConstructors & Cloning
     [StorableConstructor]
     protected EuclideanDistance(bool deserializing) : base(deserializing) { }
     protected EuclideanDistance(EuclideanDistance original, Cloner cloner) : base(original, cloner) { }
-    public override IDeepCloneable Clone(Cloner cloner) { return new EuclideanDistance(this, cloner); }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new EuclideanDistance(this, cloner);
+    }
     public EuclideanDistance() { }
     #endregion
 
-    public static double GetDistance(IReadOnlyList<double> point1, IReadOnlyList<double> point2) {
-      if (point1.Count != point2.Count) throw new ArgumentException("Euclidean distance not defined on vectors of different length");
-      var sum = 0.0;
-      for (var i = 0; i < point1.Count; i++) {
-        var d = point1[i] - point2[i];
-        sum += d * d;
+    public static double GetDistance(IEnumerable<double> point1, IEnumerable<double> point2) {
+      using (IEnumerator<double> p1Enum = point1.GetEnumerator(), p2Enum = point2.GetEnumerator()) {
+        var sum = 0.0;
+        while (p1Enum.MoveNext() & p2Enum.MoveNext()) {
+          var d = p1Enum.Current - p2Enum.Current;
+          sum += d * d;
+        }
+        if (p1Enum.MoveNext() || p2Enum.MoveNext()) throw new ArgumentException("Euclidean distance not defined on vectors of different length");
+        return Math.Sqrt(sum);
       }
-
-      return Math.Sqrt(sum);
     }
 
     public override double Get(IEnumerable<double> a, IEnumerable<double> b) {
-      return GetDistance(a.ToArray(), b.ToArray());
+      return GetDistance(a, b);
     }
   }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/ManhattanDistance.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/ManhattanDistance.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/ManhattanDistance.cs	(revision 15532)
@@ -31,5 +31,4 @@
   [Item("ManhattanDistance", "A distance function that uses block distance")]
   public class ManhattanDistance : DistanceBase<IEnumerable<double>> {
-
     #region HLConstructors & Cloning
     [StorableConstructor]
@@ -45,14 +44,16 @@
     #endregion
 
-    public static double GetDistance(double[] point1, double[] point2) {
-      if (point1.Length != point2.Length) throw new ArgumentException("Manhattan distance not defined on vectors of different length");
-      var sum = 0.0;
-      for (var i = 0; i < point1.Length; i++)
-        sum += Math.Abs(point1[i] + point2[i]);
-      return sum;
+    public static double GetDistance(IEnumerable<double> point1, IEnumerable<double> point2) {
+      using (IEnumerator<double> p1Enum = point1.GetEnumerator(), p2Enum = point2.GetEnumerator()) {
+        var sum = 0.0;
+        while (p1Enum.MoveNext() & p2Enum.MoveNext())
+          sum += Math.Abs(p1Enum.Current - p2Enum.Current);
+        if (p1Enum.MoveNext() || p2Enum.MoveNext()) throw new ArgumentException("Manhattan distance not defined on vectors of different length");
+        return sum;
+      }
     }
 
     public override double Get(IEnumerable<double> a, IEnumerable<double> b) {
-      return GetDistance(a.ToArray(), b.ToArray());
+      return GetDistance(a, b);
     }
   }
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/WeightedEuclideanDistance.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/WeightedEuclideanDistance.cs	(revision 15532)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/WeightedEuclideanDistance.cs	(revision 15532)
@@ -0,0 +1,125 @@
+﻿#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;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  [Item("WeightedEuclideanDistance", "A weighted norm function that uses Euclidean distance √(Σ(w[i]²*(p1[i]-p2[i])²))")]
+  public class WeightedEuclideanDistance : ParameterizedNamedItem, IDistance<IEnumerable<double>> {
+    [Storable]
+    private double[] weights;
+    public const string WeightsParameterName = "Weights";
+    public IValueParameter<DoubleArray> WeightsParameter {
+      get { return (IValueParameter<DoubleArray>) Parameters[WeightsParameterName]; }
+    }
+
+    public DoubleArray Weights {
+      get { return WeightsParameter.Value; }
+      set { WeightsParameter.Value = value; }
+    }
+
+    #region HLConstructors & Cloning
+    [StorableConstructor]
+    protected WeightedEuclideanDistance(bool deserializing) : base(deserializing) { }
+    private void AfterDeserialization() {
+      RegisterParameterEvents();
+    }
+    protected WeightedEuclideanDistance(WeightedEuclideanDistance original, Cloner cloner) : base(original, cloner) {
+      RegisterParameterEvents();
+      weights = original.weights != null ? original.weights.ToArray() : null;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new WeightedEuclideanDistance(this, cloner);
+    }
+    public WeightedEuclideanDistance() {
+      Parameters.Add(new ValueParameter<DoubleArray>(WeightsParameterName, "The weights used to modify the euclidean distance.", new DoubleArray(new[] {1.0})));
+      RegisterParameterEvents();
+    }
+    #endregion
+
+    public static double GetDistance(IEnumerable<double> point1, IEnumerable<double> point2, IEnumerable<double> weights) {
+      using (IEnumerator<double> p1Enum = point1.GetEnumerator(), p2Enum = point2.GetEnumerator(), weEnum = weights.GetEnumerator()) {
+        var sum = 0.0;
+        while (p1Enum.MoveNext() & p2Enum.MoveNext() & weEnum.MoveNext()) {
+          var d = p1Enum.Current - p2Enum.Current;
+          var w = weEnum.Current;
+          sum += d * d * w * w;
+        }
+        if (weEnum.MoveNext() || p1Enum.MoveNext() || p2Enum.MoveNext()) throw new ArgumentException("Weighted Euclidean distance not defined on vectors of different length");
+        return Math.Sqrt(sum);
+      }
+    }
+
+    public double Get(IEnumerable<double> a, IEnumerable<double> b) {
+      return GetDistance(a, b, weights);
+    }
+    public IComparer<IEnumerable<double>> GetDistanceComparer(IEnumerable<double> item) {
+      return new DistanceBase<IEnumerable<double>>.DistanceComparer(item, this);
+    }
+    public double Get(object x, object y) {
+      return Get((IEnumerable<double>) x, (IEnumerable<double>) y);
+    }
+    public IComparer GetDistanceComparer(object item) {
+      return new DistanceBase<IEnumerable<double>>.DistanceComparer((IEnumerable<double>) item, this);
+    }
+
+    public void AdaptToProblemData(IDataAnalysisProblemData problemData) {
+      Weights = new DoubleArray(problemData.AllowedInputVariables.Select(v => Weights.ElementNames.Contains(v) ? GetWeight(v) : 1).ToArray())
+        {ElementNames = problemData.AllowedInputVariables};
+    }
+    public void Initialize(IDataAnalysisProblemData problemData) {
+      if (Weights.Length != problemData.AllowedInputVariables.Count()) throw new ArgumentException("Number of Weights does not match the number of input variables");
+      weights = Weights.ElementNames.All(v => v == null || v.Equals(string.Empty)) ? 
+        Weights.ToArray() : 
+        problemData.AllowedInputVariables.Select(GetWeight).ToArray();
+    }
+    private double GetWeight(string v) {
+      var w = Weights;
+      var names = w.ElementNames.ToArray();
+      for (var i = 0; i < w.Length; i++) if (names[i].Equals(v)) return w[i];
+      throw new ArgumentException("weigth for " + v + " was requested but not specified.");
+    }
+    private void RegisterParameterEvents() {
+      WeightsParameter.ValueChanged += OnWeightsArrayChanged;
+      WeightsParameter.Value.ItemChanged += OnWeightChanged;
+    }
+    private void OnWeightChanged(object sender, EventArgs<int> e) {
+      WeightsParameter.Value.ItemChanged -= OnWeightChanged;
+      Weights[e.Value] = Math.Max(0, Weights[e.Value]);
+      WeightsParameter.Value.ItemChanged -= OnWeightChanged;
+    }
+    private void OnWeightsArrayChanged(object sender, EventArgs e) {
+      for (var i = 0; i < Weights.Length; i++)
+        Weights[i] = Math.Max(0, Weights[i]);
+      WeightsParameter.Value.ItemChanged += OnWeightChanged;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs	(revision 15532)
@@ -53,9 +53,9 @@
     }
     public new IDataAnalysisProblem Problem {
-      get { return (IDataAnalysisProblem)base.Problem; }
+      get { return (IDataAnalysisProblem) base.Problem; }
       set { base.Problem = value; }
     }
 
-    #region parameter names
+    #region Parameter names
     private const string DistanceFunctionParameterName = "DistanceFunction";
     private const string PerplexityParameterName = "Perplexity";
@@ -72,8 +72,9 @@
     private const string ClassesNameParameterName = "ClassesName";
     private const string NormalizationParameterName = "Normalization";
+    private const string RandomInitializationParameterName = "RandomInitialization";
     private const string UpdateIntervalParameterName = "UpdateInterval";
     #endregion
 
-    #region result names
+    #region Result names
     private const string IterationResultName = "Iteration";
     private const string ErrorResultName = "Error";
@@ -83,49 +84,52 @@
     #endregion
 
-    #region parameter properties
+    #region Parameter properties
     public IFixedValueParameter<DoubleValue> PerplexityParameter {
-      get { return Parameters[PerplexityParameterName] as IFixedValueParameter<DoubleValue>; }
+      get { return (IFixedValueParameter<DoubleValue>) Parameters[PerplexityParameterName]; }
     }
     public IFixedValueParameter<PercentValue> ThetaParameter {
-      get { return Parameters[ThetaParameterName] as IFixedValueParameter<PercentValue>; }
+      get { return (IFixedValueParameter<PercentValue>) Parameters[ThetaParameterName]; }
     }
     public IFixedValueParameter<IntValue> NewDimensionsParameter {
-      get { return Parameters[NewDimensionsParameterName] as IFixedValueParameter<IntValue>; }
+      get { return (IFixedValueParameter<IntValue>) Parameters[NewDimensionsParameterName]; }
     }
     public IConstrainedValueParameter<IDistance<double[]>> DistanceFunctionParameter {
-      get { return Parameters[DistanceFunctionParameterName] as IConstrainedValueParameter<IDistance<double[]>>; }
+      get { return (IConstrainedValueParameter<IDistance<double[]>>) Parameters[DistanceFunctionParameterName]; }
     }
     public IFixedValueParameter<IntValue> MaxIterationsParameter {
-      get { return Parameters[MaxIterationsParameterName] as IFixedValueParameter<IntValue>; }
+      get { return (IFixedValueParameter<IntValue>) Parameters[MaxIterationsParameterName]; }
     }
     public IFixedValueParameter<IntValue> StopLyingIterationParameter {
-      get { return Parameters[StopLyingIterationParameterName] as IFixedValueParameter<IntValue>; }
+      get { return (IFixedValueParameter<IntValue>) Parameters[StopLyingIterationParameterName]; }
     }
     public IFixedValueParameter<IntValue> MomentumSwitchIterationParameter {
-      get { return Parameters[MomentumSwitchIterationParameterName] as IFixedValueParameter<IntValue>; }
+      get { return (IFixedValueParameter<IntValue>) Parameters[MomentumSwitchIterationParameterName]; }
     }
     public IFixedValueParameter<DoubleValue> InitialMomentumParameter {
-      get { return Parameters[InitialMomentumParameterName] as IFixedValueParameter<DoubleValue>; }
+      get { return (IFixedValueParameter<DoubleValue>) Parameters[InitialMomentumParameterName]; }
     }
     public IFixedValueParameter<DoubleValue> FinalMomentumParameter {
-      get { return Parameters[FinalMomentumParameterName] as IFixedValueParameter<DoubleValue>; }
+      get { return (IFixedValueParameter<DoubleValue>) Parameters[FinalMomentumParameterName]; }
     }
     public IFixedValueParameter<DoubleValue> EtaParameter {
-      get { return Parameters[EtaParameterName] as IFixedValueParameter<DoubleValue>; }
+      get { return (IFixedValueParameter<DoubleValue>) Parameters[EtaParameterName]; }
     }
     public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
-      get { return Parameters[SetSeedRandomlyParameterName] as IFixedValueParameter<BoolValue>; }
+      get { return (IFixedValueParameter<BoolValue>) Parameters[SetSeedRandomlyParameterName]; }
     }
     public IFixedValueParameter<IntValue> SeedParameter {
-      get { return Parameters[SeedParameterName] as IFixedValueParameter<IntValue>; }
+      get { return (IFixedValueParameter<IntValue>) Parameters[SeedParameterName]; }
     }
     public IConstrainedValueParameter<StringValue> ClassesNameParameter {
-      get { return Parameters[ClassesNameParameterName] as IConstrainedValueParameter<StringValue>; }
+      get { return (IConstrainedValueParameter<StringValue>) Parameters[ClassesNameParameterName]; }
     }
     public IFixedValueParameter<BoolValue> NormalizationParameter {
-      get { return Parameters[NormalizationParameterName] as IFixedValueParameter<BoolValue>; }
+      get { return (IFixedValueParameter<BoolValue>) Parameters[NormalizationParameterName]; }
+    }
+    public IFixedValueParameter<BoolValue> RandomInitializationParameter {
+      get { return (IFixedValueParameter<BoolValue>) Parameters[RandomInitializationParameterName]; }
     }
     public IFixedValueParameter<IntValue> UpdateIntervalParameter {
-      get { return Parameters[UpdateIntervalParameterName] as IFixedValueParameter<IntValue>; }
+      get { return (IFixedValueParameter<IntValue>) Parameters[UpdateIntervalParameterName]; }
     }
     #endregion
@@ -187,5 +191,8 @@
       set { NormalizationParameter.Value.Value = value; }
     }
-
+    public bool RandomInitialization {
+      get { return RandomInitializationParameter.Value.Value; }
+      set { RandomInitializationParameter.Value.Value = value; }
+    }
     public int UpdateInterval {
       get { return UpdateIntervalParameter.Value.Value; }
@@ -194,18 +201,37 @@
     #endregion
 
+    #region Storable poperties
+    [Storable]
+    private Dictionary<string, List<int>> dataRowNames;
+    [Storable]
+    private Dictionary<string, ScatterPlotDataRow> dataRows;
+    [Storable]
+    private TSNEStatic<double[]>.TSNEState state;
+    [Storable]
+    private int iter;
+    #endregion
+
     #region Constructors & Cloning
     [StorableConstructor]
     private TSNEAlgorithm(bool deserializing) : base(deserializing) { }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (Parameters.ContainsKey(RandomInitializationParameterName))
+        Parameters.Add(new FixedValueParameter<BoolValue>(RandomInitializationParameterName, "Wether data points should be randomly initialized or according to the first 2 dimensions", new BoolValue(true)));
+      RegisterParameterEvents();
+    }
     private TSNEAlgorithm(TSNEAlgorithm original, Cloner cloner) : base(original, cloner) {
       if (original.dataRowNames != null)
-        this.dataRowNames = new Dictionary<string, List<int>>(original.dataRowNames);
+        dataRowNames = new Dictionary<string, List<int>>(original.dataRowNames);
       if (original.dataRows != null)
-        this.dataRows = original.dataRows.ToDictionary(kvp => kvp.Key, kvp => cloner.Clone(kvp.Value));
+        dataRows = original.dataRows.ToDictionary(kvp => kvp.Key, kvp => cloner.Clone(kvp.Value));
       if (original.state != null)
-        this.state = cloner.Clone(original.state);
-      this.iter = original.iter;
-    }
-    public override IDeepCloneable Clone(Cloner cloner) { return new TSNEAlgorithm(this, cloner); }
+        state = cloner.Clone(original.state);
+      iter = original.iter;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TSNEAlgorithm(this, cloner);
+    }
     public TSNEAlgorithm() {
       var distances = new ItemSet<IDistance<double[]>>(ApplicationManager.Manager.GetInstances<IDistance<double[]>>());
@@ -213,9 +239,9 @@
       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<PercentValue>(ThetaParameterName, "Value describing how much appoximated " +
-                                                                              "gradients my differ from exact gradients. Set to 0 for exact calculation and in [0,1] otherwise. " +
-                                                                              "Appropriate values for theta are between 0.1 and 0.7 (default = 0.5). CAUTION: exact calculation of " +
-                                                                              "forces requires building a non-sparse N*N matrix where N is the number of data points. This may " +
-                                                                              "exceed memory limitations. The function is designed to run on large (N > 5000) data sets. It may give" +
-                                                                              " poor performance on very small data sets(it is better to use a standard t - SNE implementation on such data).", new PercentValue(0)));
+                                                                               "gradients my differ from exact gradients. Set to 0 for exact calculation and in [0,1] otherwise. " +
+                                                                               "Appropriate values for theta are between 0.1 and 0.7 (default = 0.5). CAUTION: exact calculation of " +
+                                                                               "forces requires building a non-sparse N*N matrix where N is the number of data points. This may " +
+                                                                               "exceed memory limitations. The function is designed to run on large (N > 5000) data sets. It may give" +
+                                                                               " poor performance on very small data sets(it is better to use a standard t - SNE implementation on such data).", new PercentValue(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)));
@@ -230,4 +256,6 @@
       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)));
       Parameters.Add(new FixedValueParameter<IntValue>(UpdateIntervalParameterName, "The interval after which the results will be updated.", new IntValue(50)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(RandomInitializationParameterName, "Wether data points should be randomly initialized or according to the first 2 dimensions", new BoolValue(true)));
+
       Parameters[UpdateIntervalParameterName].Hidden = true;
 
@@ -238,15 +266,7 @@
       EtaParameter.Hidden = false;
       Problem = new RegressionProblem();
-    }
-    #endregion
-
-    [Storable]
-    private Dictionary<string, List<int>> dataRowNames;
-    [Storable]
-    private Dictionary<string, ScatterPlotDataRow> dataRows;
-    [Storable]
-    private TSNEStatic<double[]>.TSNEState state;
-    [Storable]
-    private int iter;
+      RegisterParameterEvents();
+    }
+    #endregion
 
     public override void Prepare() {
@@ -259,25 +279,33 @@
     protected override void Run(CancellationToken cancellationToken) {
       var problemData = Problem.ProblemData;
-      // set up and initialized everything if necessary
+      // set up and initialize everything if necessary
+      var wdist = DistanceFunction as WeightedEuclideanDistance;
+      if (wdist != null) wdist.Initialize(problemData);
       if (state == null) {
         if (SetSeedRandomly) Seed = new System.Random().Next();
-        var random = new MersenneTwister((uint)Seed);
+        var random = new MersenneTwister((uint) Seed);
         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);
-
-        state = TSNEStatic<double[]>.CreateState(data, DistanceFunction, random, NewDimensions, Perplexity, Theta,
-          StopLyingIteration, MomentumSwitchIteration, InitialMomentum, FinalMomentum, Eta);
-
-        SetUpResults(data);
+        var allindices = Problem.ProblemData.AllIndices.ToArray();
+
+        // jagged array is required to meet the static method declarations of TSNEStatic<T> 
+        var data = Enumerable.Range(0, dataset.Rows).Select(x => new double[allowedInputVariables.Length]).ToArray();
+        var col = 0;
+        foreach (var s in allowedInputVariables) {
+          var row = 0;
+          foreach (var d in dataset.GetDoubleValues(s)) {
+            data[row][col] = d;
+            row++;
+          }
+          col++;
+        }
+
+        if (Normalization) data = NormalizeInputData(data);
+        state = TSNEStatic<double[]>.CreateState(data, DistanceFunction, random, NewDimensions, Perplexity, Theta, StopLyingIteration, MomentumSwitchIteration, InitialMomentum, FinalMomentum, Eta, RandomInitialization);
+        SetUpResults(allindices);
         iter = 0;
       }
       for (; iter < MaxIterations && !cancellationToken.IsCancellationRequested; iter++) {
-        if (iter % UpdateInterval == 0)
-          Analyze(state);
+        if (iter % UpdateInterval == 0) Analyze(state);
         TSNEStatic<double[]>.Iterate(state);
       }
@@ -296,4 +324,5 @@
       Problem.ProblemDataChanged += OnProblemDataChanged;
     }
+
     protected override void DeregisterProblemEvents() {
       base.DeregisterProblemEvents();
@@ -301,6 +330,19 @@
     }
 
+    protected override void OnStopped() {
+      base.OnStopped();
+      state = null;
+      dataRowNames = null;
+      dataRows = null;
+    }
+
     private void OnProblemDataChanged(object sender, EventArgs args) {
       if (Problem == null || Problem.ProblemData == null) return;
+      OnPerplexityChanged(this, null);
+      OnColumnsChanged(this, null);
+      Problem.ProblemData.Changed += OnPerplexityChanged;
+      Problem.ProblemData.Changed += OnColumnsChanged;
+      Problem.ProblemData.Dataset.RowsChanged += OnPerplexityChanged;
+      Problem.ProblemData.Dataset.ColumnsChanged += OnColumnsChanged;
       if (!Parameters.ContainsKey(ClassesNameParameterName)) return;
       ClassesNameParameter.ValidValues.Clear();
@@ -308,8 +350,24 @@
     }
 
+    private void OnColumnsChanged(object sender, EventArgs e) {
+      if (Problem == null || Problem.ProblemData == null || Problem.ProblemData.Dataset == null || !Parameters.ContainsKey(DistanceFunctionParameterName)) return;
+      DistanceFunctionParameter.ValidValues.OfType<WeightedEuclideanDistance>().Single().AdaptToProblemData(Problem.ProblemData);
+    }
+
+    private void RegisterParameterEvents() {
+      PerplexityParameter.Value.ValueChanged -= OnPerplexityChanged;
+      PerplexityParameter.Value.ValueChanged += OnPerplexityChanged;
+    }
+
+    private void OnPerplexityChanged(object sender, EventArgs e) {
+      if (Problem == null || Problem.ProblemData == null || Problem.ProblemData.Dataset == null || !Parameters.ContainsKey(PerplexityParameterName)) return;
+      PerplexityParameter.Value.ValueChanged -= OnPerplexityChanged;
+      PerplexityParameter.Value.Value = Math.Max(1, Math.Min((Problem.ProblemData.Dataset.Rows - 1) / 3.0, Perplexity));
+      PerplexityParameter.Value.ValueChanged += OnPerplexityChanged;
+    }
     #endregion
 
     #region Helpers
-    private void SetUpResults(IReadOnlyCollection<double[]> data) {
+    private void SetUpResults(IReadOnlyList<int> allIndices) {
       if (Results == null) return;
       var results = Results;
@@ -318,51 +376,83 @@
       var problemData = Problem.ProblemData;
 
+      if (!results.ContainsKey(IterationResultName)) results.Add(new Result(IterationResultName, new IntValue(0)));
+      if (!results.ContainsKey(ErrorResultName)) results.Add(new Result(ErrorResultName, new DoubleValue(0)));
+      if (!results.ContainsKey(ScatterPlotResultName)) results.Add(new Result(ScatterPlotResultName, "Plot of the projected data", new ScatterPlot(DataResultName, "")));
+      if (!results.ContainsKey(DataResultName)) results.Add(new Result(DataResultName, "Projected Data", new DoubleMatrix()));
+      if (!results.ContainsKey(ErrorPlotResultName)) {
+        var errortable = new DataTable(ErrorPlotResultName, "Development of errors during gradient descent") {
+          VisualProperties = {
+            XAxisTitle = "UpdateIntervall",
+            YAxisTitle = "Error",
+            YAxisLogScale = true
+          }
+        };
+        errortable.Rows.Add(new DataRow("Errors"));
+        errortable.Rows["Errors"].VisualProperties.StartIndexZero = true;
+        results.Add(new Result(ErrorPlotResultName, errortable));
+      }
+
       //color datapoints acording to classes variable (be it double or string)
-      if (problemData.Dataset.VariableNames.Contains(ClassesName)) {
-        if ((problemData.Dataset as Dataset).VariableHasType<string>(ClassesName)) {
-          var classes = problemData.Dataset.GetStringValues(ClassesName).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>(ClassesName)) {
-          var classValues = problemData.Dataset.GetDoubleValues(ClassesName).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>());
-            dataRows.Add(contourname, new ScatterPlotDataRow(contourname, "", new List<Point2D<double>>()));
-            dataRows[contourname].VisualProperties.Color = GetHeatMapColor(i, contours);
-            dataRows[contourname].VisualProperties.PointSize = i + 3;
-          }
-          for (var i = 0; i < classValues.Length; i++) {
-            dataRowNames[GetContourName(classValues[i], min, max, contours)].Add(i);
-          }
-        }
-      } else {
+      if (!problemData.Dataset.VariableNames.Contains(ClassesName)) {
         dataRowNames.Add("Training", problemData.TrainingIndices.ToList());
         dataRowNames.Add("Test", problemData.TestIndices.ToList());
-      }
-
-      if (!results.ContainsKey(IterationResultName)) results.Add(new Result(IterationResultName, new IntValue(0)));
-      else ((IntValue)results[IterationResultName].Value).Value = 0;
-
-      if (!results.ContainsKey(ErrorResultName)) results.Add(new Result(ErrorResultName, new DoubleValue(0)));
-      else ((DoubleValue)results[ErrorResultName].Value).Value = 0;
-
-      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 data table in results collection");
-
-      if (!plot.Rows.ContainsKey("errors")) plot.Rows.Add(new DataRow("errors"));
-      plot.Rows["errors"].Values.Clear();
-      plot.Rows["errors"].VisualProperties.StartIndexZero = true;
-
-      results.Add(new Result(ScatterPlotResultName, "Plot of the projected data", new ScatterPlot(DataResultName, "")));
-      results.Add(new Result(DataResultName, "Projected Data", new DoubleMatrix()));
+        return;
+      }
+      var classificationData = problemData as ClassificationProblemData;
+      if (classificationData != null && classificationData.TargetVariable.Equals(ClassesName)) {
+        var classNames = classificationData.ClassValues.Zip(classificationData.ClassNames, (v, n) => new {v, n}).ToDictionary(x => x.v, x => x.n);
+        var classes = classificationData.Dataset.GetDoubleValues(classificationData.TargetVariable, allIndices).Select(v => classNames[v]).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 (((Dataset) problemData.Dataset).VariableHasType<string>(ClassesName)) {
+        var classes = problemData.Dataset.GetStringValues(ClassesName, allIndices).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 (((Dataset) problemData.Dataset).VariableHasType<double>(ClassesName)) {
+        var clusterdata = new Dataset(problemData.Dataset.DoubleVariables, problemData.Dataset.DoubleVariables.Select(v => problemData.Dataset.GetDoubleValues(v, allIndices).ToList()));
+        const int contours = 8;
+        Dictionary<int, string> contourMap;
+        IClusteringModel clusterModel;
+        double[][] borders;
+        CreateClusters(clusterdata, ClassesName, contours, out clusterModel, out contourMap, out borders);
+        var contourorder = borders.Select((x, i) => new {x, i}).OrderBy(x => x.x[0]).Select(x => x.i).ToArray();
+        for (var i = 0; i < contours; i++) {
+          var c = contourorder[i];
+          var contourname = contourMap[c];
+          dataRowNames.Add(contourname, new List<int>());
+          dataRows.Add(contourname, new ScatterPlotDataRow(contourname, "", new List<Point2D<double>>()));
+          dataRows[contourname].VisualProperties.Color = GetHeatMapColor(i, contours);
+        }
+        var allClusters = clusterModel.GetClusterValues(clusterdata, Enumerable.Range(0, clusterdata.Rows)).ToArray();
+        for (var i = 0; i < clusterdata.Rows; i++) dataRowNames[contourMap[allClusters[i] - 1]].Add(i);
+      }
+      else if (((Dataset) problemData.Dataset).VariableHasType<DateTime>(ClassesName)) {
+        var clusterdata = new Dataset(problemData.Dataset.DateTimeVariables, problemData.Dataset.DateTimeVariables.Select(v => problemData.Dataset.GetDoubleValues(v, allIndices).ToList()));
+        const int contours = 8;
+        Dictionary<int, string> contourMap;
+        IClusteringModel clusterModel;
+        double[][] borders;
+        CreateClusters(clusterdata, ClassesName, contours, out clusterModel, out contourMap, out borders);
+        var contourorder = borders.Select((x, i) => new {x, i}).OrderBy(x => x.x[0]).Select(x => x.i).ToArray();
+        for (var i = 0; i < contours; i++) {
+          var c = contourorder[i];
+          var contourname = contourMap[c];
+          dataRowNames.Add(contourname, new List<int>());
+          dataRows.Add(contourname, new ScatterPlotDataRow(contourname, "", new List<Point2D<double>>()));
+          dataRows[contourname].VisualProperties.Color = GetHeatMapColor(i, contours);
+        }
+        var allClusters = clusterModel.GetClusterValues(clusterdata, Enumerable.Range(0, clusterdata.Rows)).ToArray();
+        for (var i = 0; i < clusterdata.Rows; i++) dataRowNames[contourMap[allClusters[i] - 1]].Add(i);
+      }
+      else {
+        dataRowNames.Add("Training", problemData.TrainingIndices.ToList());
+        dataRowNames.Add("Test", problemData.TestIndices.ToList());
+      }
     }
 
@@ -372,11 +462,11 @@
       var plot = results[ErrorPlotResultName].Value as DataTable;
       if (plot == null) throw new ArgumentException("Could not create/access error data table in results collection.");
-      var errors = plot.Rows["errors"].Values;
+      var errors = plot.Rows["Errors"].Values;
       var c = tsneState.EvaluateError();
       errors.Add(c);
-      ((IntValue)results[IterationResultName].Value).Value = tsneState.iter;
-      ((DoubleValue)results[ErrorResultName].Value).Value = errors.Last();
-
-      var ndata = Normalize(tsneState.newData);
+      ((IntValue) results[IterationResultName].Value).Value = tsneState.iter;
+      ((DoubleValue) results[ErrorResultName].Value).Value = errors.Last();
+
+      var ndata = NormalizeProjectedData(tsneState.newData);
       results[DataResultName].Value = new DoubleMatrix(ndata);
       var splot = results[ScatterPlotResultName].Value as ScatterPlot;
@@ -386,11 +476,13 @@
     private void FillScatterPlot(double[,] lowDimData, ScatterPlot plot) {
       foreach (var rowName in dataRowNames.Keys) {
-        if (!plot.Rows.ContainsKey(rowName))
+        if (!plot.Rows.ContainsKey(rowName)) {
           plot.Rows.Add(dataRows.ContainsKey(rowName) ? dataRows[rowName] : new ScatterPlotDataRow(rowName, "", new List<Point2D<double>>()));
+          plot.Rows[rowName].VisualProperties.PointSize = 8;
+        }
         plot.Rows[rowName].Points.Replace(dataRowNames[rowName].Select(i => new Point2D<double>(lowDimData[i, 0], lowDimData[i, 1])));
       }
     }
 
-    private static double[,] Normalize(double[,] data) {
+    private static double[,] NormalizeProjectedData(double[,] data) {
       var max = new double[data.GetLength(1)];
       var min = new double[data.GetLength(1)];
@@ -398,15 +490,15 @@
       for (var i = 0; i < max.Length; i++) max[i] = min[i] = data[0, i];
       for (var i = 0; i < data.GetLength(0); i++)
-        for (var j = 0; j < data.GetLength(1); j++) {
-          var v = data[i, j];
-          max[j] = Math.Max(max[j], v);
-          min[j] = Math.Min(min[j], v);
-        }
+      for (var j = 0; j < data.GetLength(1); j++) {
+        var v = data[i, j];
+        max[j] = Math.Max(max[j], v);
+        min[j] = Math.Min(min[j], v);
+      }
       for (var i = 0; i < data.GetLength(0); i++) {
         for (var j = 0; j < data.GetLength(1); j++) {
           var d = max[j] - min[j];
-          var s = data[i, j] - (max[j] + min[j]) / 2;  //shift data
-          if (d.IsAlmost(0)) res[i, j] = data[i, j];   //no scaling possible
-          else res[i, j] = s / d;  //scale data
+          var s = data[i, j] - (max[j] + min[j]) / 2; //shift data
+          if (d.IsAlmost(0)) res[i, j] = data[i, j]; //no scaling possible
+          else res[i, j] = s / d; //scale data
         }
       }
@@ -414,7 +506,7 @@
     }
 
-    private static double[][] NormalizeData(IReadOnlyList<double[]> data) {
+    private static double[][] NormalizeInputData(IReadOnlyList<IReadOnlyList<double>> data) {
       // as in tSNE implementation by van der Maaten
-      var n = data[0].Length;
+      var n = data[0].Count;
       var mean = new double[n];
       var max = new double[n];
@@ -432,18 +524,31 @@
 
     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) + ")";
+      return ConvertTotalToRgb(0, noContours, contourNr);
+    }
+
+    private static void CreateClusters(IDataset data, string target, int contours, out IClusteringModel contourCluster, out Dictionary<int, string> contourNames, out double[][] borders) {
+      var cpd = new ClusteringProblemData((Dataset) data, new[] {target});
+      contourCluster = KMeansClustering.CreateKMeansSolution(cpd, contours, 3).Model;
+
+      borders = Enumerable.Range(0, contours).Select(x => new[] {double.MaxValue, double.MinValue}).ToArray();
+      var clusters = contourCluster.GetClusterValues(cpd.Dataset, cpd.AllIndices).ToArray();
+      var targetvalues = cpd.Dataset.GetDoubleValues(target).ToArray();
+      foreach (var i in cpd.AllIndices) {
+        var cl = clusters[i] - 1;
+        var clv = targetvalues[i];
+        if (borders[cl][0] > clv) borders[cl][0] = clv;
+        if (borders[cl][1] < clv) borders[cl][1] = clv;
+      }
+
+      contourNames = new Dictionary<int, string>();
+      for (var i = 0; i < contours; i++)
+        contourNames.Add(i, "[" + borders[i][0] + ";" + borders[i][1] + "]");
+    }
+
+    private static Color ConvertTotalToRgb(double low, double high, double cell) {
+      var colorGradient = ColorGradient.Colors;
+      var range = high - low;
+      var h = Math.Min(cell / range * colorGradient.Count, colorGradient.Count - 1);
+      return colorGradient[(int) h];
     }
     #endregion
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs	(revision 15532)
@@ -65,5 +65,4 @@
   [StorableClass]
   public class TSNEStatic<T> {
-
     [StorableClass]
     public sealed class TSNEState : DeepCloneable {
@@ -170,5 +169,7 @@
       [StorableConstructor]
       public TSNEState(bool deserializing) { }
-      public TSNEState(T[] data, IDistance<T> distance, IRandom random, int newDimensions, double perplexity, double theta, int stopLyingIter, int momSwitchIter, double momentum, double finalMomentum, double eta) {
+
+      public TSNEState(IReadOnlyList<T> data, IDistance<T> distance, IRandom random, int newDimensions, double perplexity,
+        double theta, int stopLyingIter, int momSwitchIter, double momentum, double finalMomentum, double eta, bool randomInit) {
         this.distance = distance;
         this.random = random;
@@ -183,5 +184,5 @@
 
         // initialize
-        noDatapoints = data.Length;
+        noDatapoints = data.Count;
         if (noDatapoints - 1 < 3 * perplexity)
           throw new ArgumentException("Perplexity too large for the number of data points!");
@@ -193,6 +194,6 @@
         gains = new double[noDatapoints, newDimensions];
         for (var i = 0; i < noDatapoints; i++)
-          for (var j = 0; j < newDimensions; j++)
-            gains[i, j] = 1.0;
+        for (var j = 0; j < newDimensions; j++)
+          gains[i, j] = 1.0;
 
         p = null;
@@ -212,19 +213,24 @@
         var rand = new NormalDistributedRandom(random, 0, 1);
         for (var i = 0; i < noDatapoints; i++)
-          for (var j = 0; j < newDimensions; j++)
-            newData[i, j] = rand.NextDouble() * .0001;
+        for (var j = 0; j < newDimensions; j++)
+          newData[i, j] = rand.NextDouble() * .0001;
+
+        if (!(data[0] is IReadOnlyList<double>) || randomInit) return;
+        for (var i = 0; i < noDatapoints; i++)
+        for (var j = 0; j < newDimensions; j++) {
+          var row = (IReadOnlyList<double>) data[i];
+          newData[i, j] = row[j % row.Count];
+        }
       }
       #endregion
 
       public double EvaluateError() {
-        return exact ?
-          EvaluateErrorExact(p, newData, noDatapoints, newDimensions) :
-          EvaluateErrorApproximate(rowP, colP, valP, newData, theta);
+        return exact ? EvaluateErrorExact(p, newData, noDatapoints, newDimensions) : EvaluateErrorApproximate(rowP, colP, valP, newData, theta);
       }
 
       #region Helpers
-      private static void CalculateApproximateSimilarities(T[] data, IDistance<T> distance, double perplexity, out int[] rowP, out int[] colP, out double[] valP) {
+      private static void CalculateApproximateSimilarities(IReadOnlyList<T> data, IDistance<T> distance, double perplexity, out int[] rowP, out int[] colP, out double[] valP) {
         // Compute asymmetric pairwise input similarities
-        ComputeGaussianPerplexity(data, distance, out rowP, out colP, out valP, perplexity, (int)(3 * perplexity));
+        ComputeGaussianPerplexity(data, distance, out rowP, out colP, out valP, perplexity, (int) (3 * perplexity));
         // Symmetrize input similarities
         int[] sRowP, symColP;
@@ -235,15 +241,14 @@
         valP = sValP;
         var sumP = .0;
-        for (var i = 0; i < rowP[data.Length]; i++) sumP += valP[i];
-        for (var i = 0; i < rowP[data.Length]; i++) valP[i] /= sumP;
-      }
-
-      private static double[,] CalculateExactSimilarites(T[] data, IDistance<T> distance, double perplexity) {
+        for (var i = 0; i < rowP[data.Count]; i++) sumP += valP[i];
+        for (var i = 0; i < rowP[data.Count]; i++) valP[i] /= sumP;
+      }
+      private static double[,] CalculateExactSimilarites(IReadOnlyList<T> data, IDistance<T> distance, double perplexity) {
         // Compute similarities
-        var p = new double[data.Length, data.Length];
+        var p = new double[data.Count, data.Count];
         ComputeGaussianPerplexity(data, distance, p, perplexity);
         // Symmetrize input similarities
-        for (var n = 0; n < data.Length; n++) {
-          for (var m = n + 1; m < data.Length; m++) {
+        for (var n = 0; n < data.Count; n++) {
+          for (var m = n + 1; m < data.Count; m++) {
             p[n, m] += p[m, n];
             p[m, n] = p[n, m];
@@ -251,9 +256,16 @@
         }
         var sumP = .0;
-        for (var i = 0; i < data.Length; i++) for (var j = 0; j < data.Length; j++) sumP += p[i, j];
-        for (var i = 0; i < data.Length; i++) for (var j = 0; j < data.Length; j++) p[i, j] /= sumP;
+        for (var i = 0; i < data.Count; i++) {
+          for (var j = 0; j < data.Count; j++) {
+            sumP += p[i, j];
+          }
+        }
+        for (var i = 0; i < data.Count; i++) {
+          for (var j = 0; j < data.Count; j++) {
+            p[i, j] /= sumP;
+          }
+        }
         return p;
       }
-
       private static void ComputeGaussianPerplexity(IReadOnlyList<T> x, IDistance<T> distance, out int[] rowP, out int[] colP, out double[] valP, double perplexity, int k) {
         if (perplexity > k) throw new ArgumentException("Perplexity should be lower than k!");
@@ -290,7 +302,7 @@
 
           // Iterate until we found a good perplexity
-          var iter = 0; double sumP = 0;
+          var iter = 0;
+          double sumP = 0;
           while (!found && iter < 200) {
-
             // Compute Gaussian kernel row
             for (var m = 0; m < k; m++) curP[m] = Math.Exp(-beta * distances[m + 1]);
@@ -307,5 +319,6 @@
             if (hdiff < tol && -hdiff < tol) {
               found = true;
-            } else {
+            }
+            else {
               if (hdiff > 0) {
                 minBeta = beta;
@@ -314,5 +327,6 @@
                 else
                   beta = (beta + maxBeta) / 2.0;
-              } else {
+              }
+              else {
                 maxBeta = beta;
                 if (minBeta.IsAlmost(double.MinValue) || minBeta.IsAlmost(double.MaxValue))
@@ -335,9 +349,9 @@
         }
       }
-      private static void ComputeGaussianPerplexity(T[] x, IDistance<T> distance, double[,] p, double perplexity) {
+      private static void ComputeGaussianPerplexity(IReadOnlyList<T> x, IDistance<T> distance, double[,] p, double perplexity) {
         // Compute the distance matrix
         var dd = ComputeDistances(x, distance);
 
-        var n = x.Length;
+        var n = x.Count;
         // Compute the Gaussian kernel row by row
         for (var i = 0; i < n; i++) {
@@ -352,5 +366,5 @@
           // Iterate until we found a good perplexity
           var iter = 0;
-          while (!found && iter < 200) {      // 200 iterations as in tSNE implementation by van der Maarten
+          while (!found && iter < 200) { // 200 iterations as in tSNE implementation by van der Maarten
 
             // Compute Gaussian kernel row
@@ -369,5 +383,6 @@
             if (hdiff < tol && -hdiff < tol) {
               found = true;
-            } else {
+            }
+            else {
               if (hdiff > 0) {
                 minBeta = beta;
@@ -376,5 +391,6 @@
                 else
                   beta = (beta + maxBeta) / 2.0;
-              } else {
+              }
+              else {
                 maxBeta = beta;
                 if (minBeta.IsAlmost(double.MinValue) || minBeta.IsAlmost(double.MaxValue))
@@ -393,9 +409,8 @@
         }
       }
-
-      private static double[][] ComputeDistances(T[] x, IDistance<T> distance) {
-        var res = new double[x.Length][];
-        for (var r = 0; r < x.Length; r++) {
-          var rowV = new double[x.Length];
+      private static double[][] ComputeDistances(IReadOnlyList<T> x, IDistance<T> distance) {
+        var res = new double[x.Count][];
+        for (var r = 0; r < x.Count; r++) {
+          var rowV = new double[x.Count];
           // all distances must be symmetric 
           for (var c = 0; c < r; c++) {
@@ -403,5 +418,5 @@
           }
           rowV[r] = 0.0; // distance to self is zero for all distances
-          for (var c = r + 1; c < x.Length; c++) {
+          for (var c = r + 1; c < x.Count; c++) {
             rowV[c] = distance.Get(x[r], x[c]);
           }
@@ -411,5 +426,4 @@
         // return x.Select(m => x.Select(n => distance.Get(m, n)).ToArray()).ToArray();
       }
-
       private static double EvaluateErrorExact(double[,] p, double[,] y, int n, int d) {
         // Compute the squared Euclidean distance matrix
@@ -425,5 +439,6 @@
               q[n1, m] = 1 / (1 + dd[n1, m]);
               sumQ += q[n1, m];
-            } else q[n1, m] = double.Epsilon;
+            }
+            else q[n1, m] = double.Epsilon;
           }
         }
@@ -433,10 +448,9 @@
         var c = .0;
         for (var i = 0; i < n; i++)
-          for (var j = 0; j < n; j++) {
-            c += p[i, j] * Math.Log((p[i, j] + float.Epsilon) / (q[i, j] + float.Epsilon));
-          }
+        for (var j = 0; j < n; j++) {
+          c += p[i, j] * Math.Log((p[i, j] + float.Epsilon) / (q[i, j] + float.Epsilon));
+        }
         return c;
       }
-
       private static double EvaluateErrorApproximate(IReadOnlyList<int> rowP, IReadOnlyList<int> colP, IReadOnlyList<double> valP, double[,] y, double theta) {
         // Get estimate of normalization term
@@ -463,5 +477,4 @@
       }
       private static void SymmetrizeMatrix(IReadOnlyList<int> rowP, IReadOnlyList<int> colP, IReadOnlyList<double> valP, out int[] symRowP, out int[] symColP, out double[] symValP) {
-
         // Count number of elements and row counts of symmetric matrix
         var n = rowP.Count - 1;
@@ -469,5 +482,4 @@
         for (var j = 0; j < n; j++) {
           for (var i = rowP[j]; i < rowP[j + 1]; i++) {
-
             // Check whether element (col_P[i], n) is present
             var present = false;
@@ -497,5 +509,5 @@
         var offset = new int[n];
         for (var j = 0; j < n; j++) {
-          for (var i = rowP[j]; i < rowP[j + 1]; i++) {                                  // considering element(n, colP[i])
+          for (var i = rowP[j]; i < rowP[j + 1]; i++) { // considering element(n, colP[i])
 
             // Check whether element (col_P[i], n) is present
@@ -549,8 +561,7 @@
     public static double[,] Run(T[] data, IDistance<T> distance, IRandom random,
       int newDimensions = 2, double perplexity = 25, int iterations = 1000,
-      double theta = 0,
-      int stopLyingIter = 0, int momSwitchIter = 0, double momentum = .5,
+      double theta = 0, int stopLyingIter = 0, int momSwitchIter = 0, double momentum = .5,
       double finalMomentum = .8, double eta = 10.0
-      ) {
+    ) {
       var state = CreateState(data, distance, random, newDimensions, perplexity,
         theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta);
@@ -565,7 +576,7 @@
       int newDimensions = 2, double perplexity = 25, double theta = 0,
       int stopLyingIter = 0, int momSwitchIter = 0, double momentum = .5,
-      double finalMomentum = .8, double eta = 10.0
-      ) {
-      return new TSNEState(data, distance, random, newDimensions, perplexity, theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta);
+      double finalMomentum = .8, double eta = 10.0, bool randomInit = true
+    ) {
+      return new TSNEState(data, distance, random, newDimensions, perplexity, theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta, randomInit);
     }
 
@@ -580,20 +591,18 @@
         for (var j = 0; j < state.newDimensions; j++) {
           state.gains[i, j] = Math.Sign(state.dY[i, j]) != Math.Sign(state.uY[i, j])
-            ? state.gains[i, j] + .2  // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct
+            ? state.gains[i, j] + .2 // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct
             : state.gains[i, j] * .8;
-
           if (state.gains[i, j] < .01) state.gains[i, j] = .01;
         }
       }
-
 
       // Perform gradient update (with momentum and gains)
       for (var i = 0; i < state.noDatapoints; i++)
-        for (var j = 0; j < state.newDimensions; j++)
-          state.uY[i, j] = state.currentMomentum * state.uY[i, j] - state.eta * state.gains[i, j] * state.dY[i, j];
+      for (var j = 0; j < state.newDimensions; j++)
+        state.uY[i, j] = state.currentMomentum * state.uY[i, j] - state.eta * state.gains[i, j] * state.dY[i, j];
 
       for (var i = 0; i < state.noDatapoints; i++)
-        for (var j = 0; j < state.newDimensions; j++)
-          state.newData[i, j] = state.newData[i, j] + state.uY[i, j];
+      for (var j = 0; j < state.newDimensions; j++)
+        state.newData[i, j] = state.newData[i, j] + state.uY[i, j];
 
       // Make solution zero-mean
@@ -604,6 +613,6 @@
         if (state.exact)
           for (var i = 0; i < state.noDatapoints; i++)
-            for (var j = 0; j < state.noDatapoints; j++)
-              state.p[i, j] /= 12.0;
+          for (var j = 0; j < state.noDatapoints; j++)
+            state.p[i, j] /= 12.0;
         else
           for (var i = 0; i < state.rowP[state.noDatapoints]; i++)
@@ -634,7 +643,7 @@
       // Compute final t-SNE gradient
       for (var i = 0; i < n; i++)
-        for (var j = 0; j < d; j++) {
-          dC[i, j] = posF[i, j] - negF[i, j] / sumQ;
-        }
+      for (var j = 0; j < d; j++) {
+        dC[i, j] = posF[i, j] - negF[i, j] / sumQ;
+      }
     }
 
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEUtils.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEUtils.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEUtils.cs	(revision 15532)
@@ -35,12 +35,11 @@
     }
 
-    internal static IList<T> Swap<T>(this IList<T> list, int indexA, int indexB) {
+    internal static void Swap<T>(this IList<T> list, int indexA, int indexB) {
       var tmp = list[indexA];
       list[indexA] = list[indexB];
       list[indexB] = tmp;
-      return list;
     }
 
-    internal static int Partition<T>(this IList<T> list, int left, int right, int pivotindex, IComparer<T> comparer) {
+    private static int Partition<T>(this IList<T> list, int left, int right, int pivotindex, IComparer<T> comparer) {
       var pivotValue = list[pivotindex];
       list.Swap(pivotindex, right);
@@ -67,10 +66,10 @@
     /// <param name="comparer">comparer for list elemnts </param>
     /// <returns></returns>
-    internal static T NthElement<T>(this IList<T> list, int left, int right, int n, IComparer<T> comparer) {
+    internal static void PartialSort<T>(this IList<T> list, int left, int right, int n, IComparer<T> comparer) {
       while (true) {
-        if (left == right) return list[left];
-        var pivotindex = left + (int)Math.Floor(new System.Random().Next() % (right - (double)left + 1));
+        if (left == right) return;
+        var pivotindex = left + (int) Math.Floor(new System.Random().Next() % (right - (double) left + 1));
         pivotindex = list.Partition(left, right, pivotindex, comparer);
-        if (n == pivotindex) return list[n];
+        if (n == pivotindex) return;
         if (n < pivotindex) right = pivotindex - 1;
         else left = pivotindex + 1;
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VantagePointTree.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VantagePointTree.cs	(revision 15531)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/VantagePointTree.cs	(revision 15532)
@@ -139,5 +139,5 @@
       // Partition around the median distance
       var median = (upper + lower) / 2;
-      items.NthElement(lower + 1, upper - 1, median, distance.GetDistanceComparer(items[lower]));
+      items.PartialSort(lower + 1, upper - 1, median, distance.GetDistanceComparer(items[lower]));
 
       // Threshold of the new node will be the distance to the median
