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 14904)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 14911)
@@ -240,4 +240,14 @@
     <Compile Include="Interfaces\ISupportVectorMachineSolution.cs" />
     <Compile Include="Interfaces\IDataAnalysisAlgorithm.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\CicularKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\GaussianKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\IKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\InverseMultiquadraticKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\KernelBase.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\MultiquadraticKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\PolysplineKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelFunctions\ThinPlatePolysplineKernel.cs" />
+    <Compile Include="KernelRidgeRegression\KernelRidgeRegression.cs" />
+    <Compile Include="KernelRidgeRegression\KernelRidgeRegressionModel.cs" />
     <Compile Include="kMeans\KMeansClustering.cs" />
     <Compile Include="kMeans\KMeansClusteringModel.cs" />
@@ -325,4 +335,5 @@
     <Compile Include="TSNE\Distances\IndexedItemDistance.cs" />
     <Compile Include="TSNE\Distances\InnerProductDistance.cs" />
+    <Compile Include="TSNE\Distances\ManhattanDistance.cs" />
     <Compile Include="TSNE\Interfaces\IDistance.cs" />
     <Compile Include="TSNE\Interfaces\ISpacePartitioningTree.cs" />
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/CicularKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/CicularKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/CicularKernel.cs	(revision 14911)
@@ -0,0 +1,62 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  [Item("CircularKernel", "A circular kernel function 2*pi*(acos(-d)-d*(1-d²)^(0.5)) where n = ||x-c|| and d = n/beta \n  As described in http://crsouza.com/2010/03/17/kernel-functions-for-machine-learning-applications/")]
+  public class CircularKernel : KernelBase {
+
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected CircularKernel(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected CircularKernel(CircularKernel original, Cloner cloner) : base(original, cloner) { }
+    public CircularKernel() {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CircularKernel(this, cloner);
+    }
+    #endregion
+
+    protected override double Get(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      if (norm >= beta) return 0;
+      var d = norm / beta;
+      return 2 * Math.PI * (Math.Acos(-d) - d * Math.Sqrt(1 - d * d));
+    }
+
+    // 4*pi*n^3 / (beta^4 * sqrt(1-n^2/beta^2) 
+    protected override double GetGradient(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      if (beta < norm) return 0;
+      var d = norm / beta;
+      return -4 * Math.PI * d * d * d / beta * Math.Sqrt(1 - d * d);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/GaussianKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/GaussianKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/GaussianKernel.cs	(revision 14911)
@@ -0,0 +1,62 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  [Item("GaussianKernel", "A kernel function that uses Gaussian function exp(-n²/beta²). As described in http://crsouza.com/2010/03/17/kernel-functions-for-machine-learning-applications/")]
+  public class GaussianKernel : KernelBase {
+
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected GaussianKernel(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected GaussianKernel(GaussianKernel original, Cloner cloner) : base(original, cloner) { }
+    public GaussianKernel() {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GaussianKernel(this, cloner);
+    }
+    #endregion
+
+    protected override double Get(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return Math.Exp(-d * d);
+    }
+
+    //2 * n²/b²* 1/b * exp(-n²/b²)
+    protected override double GetGradient(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return 2 * d * d / beta * Math.Exp(-d * d);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/IKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/IKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/IKernel.cs	(revision 14911)
@@ -0,0 +1,28 @@
+﻿#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
+
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  public interface IKernel : ICovarianceFunction {
+    double? Beta { get; set; } // a kernel parameter
+    IDistance Distance { get; set; } // the distance function to use
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/InverseMultiquadraticKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/InverseMultiquadraticKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/InverseMultiquadraticKernel.cs	(revision 14911)
@@ -0,0 +1,60 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  [Item("InverseMultiquadraticKernel", "A kernel function that uses the inverse multi-quadratic function  1 / sqrt(1+||x-c||²/beta²). Similar to http://crsouza.com/2010/03/17/kernel-functions-for-machine-learning-applications/ with beta as a scaling factor.")]
+  public class InverseMultiquadraticKernel : KernelBase {
+
+    private const double C = 1.0;
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected InverseMultiquadraticKernel(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected InverseMultiquadraticKernel(InverseMultiquadraticKernel original, Cloner cloner) : base(original, cloner) { }
+    public InverseMultiquadraticKernel() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InverseMultiquadraticKernel(this, cloner);
+    }
+    #endregion
+
+    protected override double Get(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return 1 / Math.Sqrt(C + d * d);
+    }
+
+    //n²/(b³(n²/b² + C)^1.5)
+    protected override double GetGradient(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return d * d / (beta * Math.Pow(d * d + C, 1.5));
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/KernelBase.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/KernelBase.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/KernelBase.cs	(revision 14911)
@@ -0,0 +1,104 @@
+﻿#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  public abstract class KernelBase : ParameterizedNamedItem, IKernel {
+
+    #region Parameternames
+    private const string DistanceParameterName = "Distance";
+    #endregion
+    #region Parameterproperties
+    public ValueParameter<IDistance> DistanceParameter {
+      get { return Parameters[DistanceParameterName] as ValueParameter<IDistance>; }
+    }
+
+    [Storable]
+    public double? Beta { get; set; }
+    #endregion
+    #region Properties
+    public IDistance Distance {
+      get { return DistanceParameter.Value; }
+      set { DistanceParameter.Value = value; }
+    }
+
+    #endregion
+
+    [StorableConstructor]
+    protected KernelBase(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+
+    protected KernelBase(KernelBase original, Cloner cloner)
+      : base(original, cloner) {
+      Beta = original.Beta;
+    }
+
+    protected KernelBase() {
+      Parameters.Add(new ValueParameter<IDistance>(DistanceParameterName, "The distance function used for kernel calculation"));
+      DistanceParameter.Value = new EuclideanDistance();
+    }
+
+    public double Get(object a, object b) {
+      return Get(Distance.Get(a, b));
+    }
+
+    protected abstract double Get(double norm);
+
+    public int GetNumberOfParameters(int numberOfVariables) {
+      return Beta.HasValue ? 0 : 1;
+    }
+
+    public void SetParameter(double[] p) {
+      if (p != null && p.Length == 1) Beta = new double?(p[0]);
+    }
+
+    public ParameterizedCovarianceFunction GetParameterizedCovarianceFunction(double[] p, int[] columnIndices) {
+      if (p.Length != GetNumberOfParameters(columnIndices.Length)) throw new ArgumentException("Illegal parametrization");
+      var myClone = (KernelBase)Clone(new Cloner());
+      myClone.SetParameter(p);
+      var cov = new ParameterizedCovarianceFunction {
+        Covariance = (x, i, j) => myClone.Get(GetNorm(x, x, i, j, columnIndices)),
+        CrossCovariance = (x, xt, i, j) => myClone.Get(GetNorm(x, xt, i, j, columnIndices)),
+        CovarianceGradient = (x, i, j) => new List<double> { myClone.GetGradient(GetNorm(x, x, i, j, columnIndices)) }
+      };
+      return cov;
+    }
+
+    protected abstract double GetGradient(double norm);
+
+    protected double GetNorm(double[,] x, double[,] xt, int i, int j, int[] columnIndices) {
+      var dist = Distance as IDistance<IEnumerable<double>>;
+      if (dist == null) throw new ArgumentException("The distance needs to apply to double vectors");
+      var r1 = columnIndices.Select(c => x[i, c]);
+      var r2 = columnIndices.Select(c => xt[j, c]);
+      return dist.Get(r1, r2);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/MultiquadraticKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/MultiquadraticKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/MultiquadraticKernel.cs	(revision 14911)
@@ -0,0 +1,63 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  // conditionally positive definite. (need to add polynomials) see http://num.math.uni-goettingen.de/schaback/teaching/sc.pdf 
+  [Item("MultiquadraticKernel", "A kernel function that uses the multi-quadratic function sqrt(1+||x-c||²/beta²). Similar to http://crsouza.com/2010/03/17/kernel-functions-for-machine-learning-applications/ with beta as a scaling factor.")]
+  public class MultiquadraticKernel : KernelBase {
+
+    private const double C = 1.0;
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected MultiquadraticKernel(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected MultiquadraticKernel(MultiquadraticKernel original, Cloner cloner)
+                : base(original, cloner) { }
+
+    public MultiquadraticKernel() {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiquadraticKernel(this, cloner);
+    }
+    #endregion
+    protected override double Get(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return Math.Sqrt(C + d * d);
+    }
+
+    //-n²/(d³*sqrt(C+n²/d²))
+    protected override double GetGradient(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return -d * d / (beta * Math.Sqrt(C + d * d));
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/PolysplineKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/PolysplineKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/PolysplineKernel.cs	(revision 14911)
@@ -0,0 +1,78 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  // conditionally positive definite. (need to add polynomials) see http://num.math.uni-goettingen.de/schaback/teaching/sc.pdf 
+  [Item("PolysplineKernel", "A kernel function that uses the polyharmonic function (||x-c||/Beta)^Degree as given in http://num.math.uni-goettingen.de/schaback/teaching/sc.pdf with beta as a scaling parameters.")]
+  public class PolysplineKernel : KernelBase {
+
+    #region Parameternames
+    private const string DegreeParameterName = "Degree";
+    #endregion
+    #region Parameterproperties
+    public IFixedValueParameter<DoubleValue> DegreeParameter {
+      get { return Parameters[DegreeParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    #endregion
+    #region Properties
+    public DoubleValue Degree {
+      get { return DegreeParameter.Value; }
+    }
+    #endregion
+
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected PolysplineKernel(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected PolysplineKernel(PolysplineKernel original, Cloner cloner) : base(original, cloner) { }
+    public PolysplineKernel() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(DegreeParameterName, "The degree of the kernel. Needs to be greater than zero.", new DoubleValue(1.0)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PolysplineKernel(this, cloner);
+    }
+    #endregion
+
+    protected override double Get(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return Math.Pow(d, Degree.Value);
+    }
+
+    //-degree/beta * (norm/beta)^degree
+    protected override double GetGradient(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      return -Degree.Value / beta * Math.Pow(d, Degree.Value);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/ThinPlatePolysplineKernel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/ThinPlatePolysplineKernel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelFunctions/ThinPlatePolysplineKernel.cs	(revision 14911)
@@ -0,0 +1,80 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  // conditionally positive definite. (need to add polynomials) see http://num.math.uni-goettingen.de/schaback/teaching/sc.pdf 
+  [Item("ThinPlatePolysplineKernel", "A kernel function that uses the ThinPlatePolyspline function (||x-c||/Beta)^(Degree)*log(||x-c||/Beta) as described in \"Thin-Plate Spline Radial Basis Function Scheme for Advection-Diffusion Problems\" with beta as a scaling parameter.")]
+  public class ThinPlatePolysplineKernel : KernelBase {
+
+    #region Parameternames
+    private const string DegreeParameterName = "Degree";
+    #endregion
+    #region Parameterproperties
+    public IFixedValueParameter<DoubleValue> DegreeParameter {
+      get { return Parameters[DegreeParameterName] as IFixedValueParameter<DoubleValue>; }
+    }
+    #endregion
+    #region Properties
+    public DoubleValue Degree {
+      get { return DegreeParameter.Value; }
+    }
+    #endregion
+
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected ThinPlatePolysplineKernel(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected ThinPlatePolysplineKernel(ThinPlatePolysplineKernel original, Cloner cloner) : base(original, cloner) { }
+    public ThinPlatePolysplineKernel() {
+      Parameters.Add(new FixedValueParameter<DoubleValue>(DegreeParameterName, "The degree of the kernel. Needs to be greater than zero.", new DoubleValue(2.0)));
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ThinPlatePolysplineKernel(this, cloner);
+    }
+    #endregion
+
+    protected override double Get(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      if (Math.Abs(d) < double.Epsilon) return 0;
+      return Math.Pow(d, Degree.Value) * Math.Log(d);
+    }
+
+    // (Degree/beta) * (norm/beta)^Degree * log(norm/beta) 
+    protected override double GetGradient(double norm) {
+      var beta = Beta.Value;
+      if (Math.Abs(beta) < double.Epsilon) return double.NaN;
+      var d = norm / beta;
+      if (Math.Abs(d) < double.Epsilon) return 0;
+      return Degree.Value / beta * Math.Pow(d, Degree.Value) * Math.Log(d);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegression.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegression.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegression.cs	(revision 14911)
@@ -0,0 +1,141 @@
+#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.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [Item("Kernel Ridge Regression", "Kernelized ridge regression e.g. for radial basis function (RBF) regression.")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 100)]
+  [StorableClass]
+  public sealed class KernelRidgeRegression : BasicAlgorithm {
+    private const string SolutionResultName = "Kernel ridge regression solution";
+
+    public override bool SupportsPause {
+      get { return false; }
+    }
+    public override Type ProblemType {
+      get { return typeof(IRegressionProblem); }
+    }
+    public new IRegressionProblem Problem {
+      get { return (IRegressionProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    #region parameter names
+    private const string KernelParameterName = "Kernel";
+    private const string ScaleInputVariablesParameterName = "ScaleInputVariables";
+    private const string LambdaParameterName = "LogLambda";
+    private const string BetaParameterName = "Beta";
+    #endregion
+
+    #region parameter properties
+    public ValueParameter<IKernel> KernelParameter {
+      get { return (ValueParameter<IKernel>)Parameters[KernelParameterName]; }
+    }
+
+    public IFixedValueParameter<BoolValue> ScaleInputVariablesParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[ScaleInputVariablesParameterName]; }
+    }
+
+    public IFixedValueParameter<DoubleValue> LogLambdaParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[LambdaParameterName]; }
+    }
+
+    public IFixedValueParameter<DoubleValue> BetaParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters[BetaParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public IKernel Kernel {
+      get { return KernelParameter.Value; }
+    }
+
+    public bool ScaleInputVariables {
+      get { return ScaleInputVariablesParameter.Value.Value; }
+      set { ScaleInputVariablesParameter.Value.Value = value; }
+    }
+
+    public double LogLambda {
+      get { return LogLambdaParameter.Value.Value; }
+      set { LogLambdaParameter.Value.Value = value; }
+    }
+
+    public double Beta {
+      get { return BetaParameter.Value.Value; }
+      set { BetaParameter.Value.Value = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private KernelRidgeRegression(bool deserializing) : base(deserializing) { }
+    private KernelRidgeRegression(KernelRidgeRegression original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public KernelRidgeRegression() {
+      Problem = new RegressionProblem();
+      Parameters.Add(new ValueParameter<IKernel>(KernelParameterName, "The kernel", new GaussianKernel()));
+      Parameters.Add(new FixedValueParameter<BoolValue>(ScaleInputVariablesParameterName, "Set to true if the input variables should be scaled to the interval [0..1]", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(LambdaParameterName, "The log10-transformed weight for the regularization term lambda [-inf..+inf]. Small values produce more complex models, large values produce models with larger errors. Set to very small value (e.g. -1.0e15) for almost exact approximation", new DoubleValue(-2)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(BetaParameterName, "The beta parameter for the kernel", new DoubleValue(2)));
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KernelRidgeRegression(this, cloner);
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      double rmsError, looCvRMSE;
+      var kernel = Kernel;
+      kernel.Beta = Beta;
+      var solution = CreateRadialBasisRegressionSolution(Problem.ProblemData, kernel, Math.Pow(10, LogLambda), ScaleInputVariables, out rmsError, out looCvRMSE);
+      Results.Add(new Result(SolutionResultName, "The kernel ridge regression solution.", solution));
+      Results.Add(new Result("RMSE (test)", "The root mean squared error of the solution on the test set.", new DoubleValue(rmsError)));
+      Results.Add(new Result("RMSE (LOO-CV)", "The leave-one-out-cross-validation root mean squared error", new DoubleValue(looCvRMSE)));
+    }
+
+    public static IRegressionSolution CreateRadialBasisRegressionSolution(IRegressionProblemData problemData, ICovarianceFunction kernel, double lambda, bool scaleInputs, out double rmsError, out double looCvRMSE) {
+      var model = new KernelRidgeRegressionModel(problemData.Dataset, problemData.TargetVariable, problemData.AllowedInputVariables, problemData.TrainingIndices, scaleInputs, kernel, lambda);
+      rmsError = double.NaN;
+      if (problemData.TestIndices.Any()) {
+        rmsError = Math.Sqrt(model.GetEstimatedValues(problemData.Dataset, problemData.TestIndices)
+          .Zip(problemData.TargetVariableTestValues, (a, b) => (a - b) * (a - b))
+          .Average());
+      }
+      var solution = model.CreateRegressionSolution((IRegressionProblemData)problemData.Clone());
+      solution.Model.Name = "Kernel ridge regression model";
+      solution.Name = SolutionResultName;
+      looCvRMSE = model.LooCvRMSE;
+      return solution;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegressionModel.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegressionModel.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/KernelRidgeRegression/KernelRidgeRegressionModel.cs	(revision 14911)
@@ -0,0 +1,227 @@
+﻿#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.KernelRidgeRegression {
+  [StorableClass]
+  [Item("KernelRidgeRegressionModel", "A kernel ridge regression model")]
+  public sealed class KernelRidgeRegressionModel : RegressionModel {
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return allowedInputVariables; }
+    }
+
+    [Storable]
+    private readonly string[] allowedInputVariables;
+    public string[] AllowedInputVariables {
+      get { return allowedInputVariables; }
+    }
+
+
+    [Storable]
+    public double LooCvRMSE { get; private set; }
+
+    [Storable]
+    private readonly double[] alpha;
+
+    [Storable]
+    private readonly double[,] trainX; // it is better to store the original training dataset completely because this is more efficient in persistence
+
+    [Storable]
+    private readonly ITransformation<double>[] scaling;
+
+    [Storable]
+    private readonly ICovarianceFunction kernel;
+
+    [Storable]
+    private readonly double lambda;
+
+    [Storable]
+    private readonly double yOffset; // implementation works for zero-mean, unit-variance target variables
+
+    [Storable]
+    private readonly double yScale;
+
+    [StorableConstructor]
+    private KernelRidgeRegressionModel(bool deserializing) : base(deserializing) { }
+    private KernelRidgeRegressionModel(KernelRidgeRegressionModel original, Cloner cloner)
+      : base(original, cloner) {
+      // shallow copies of arrays because they cannot be modified
+      allowedInputVariables = original.allowedInputVariables;
+      alpha = original.alpha;
+      trainX = original.trainX;
+      scaling = original.scaling;
+      lambda = original.lambda;
+      LooCvRMSE = original.LooCvRMSE;
+
+      yOffset = original.yOffset;
+      yScale = original.yScale;
+      if (original.kernel != null)
+        kernel = cloner.Clone(original.kernel);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new KernelRidgeRegressionModel(this, cloner);
+    }
+
+    public KernelRidgeRegressionModel(IDataset dataset, string targetVariable, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows,
+      bool scaleInputs, ICovarianceFunction kernel, double lambda = 0.1) : base(targetVariable) {
+      if (kernel.GetNumberOfParameters(allowedInputVariables.Count()) > 0) throw new ArgumentException("All parameters in the kernel function must be specified.");
+      name = ItemName;
+      description = ItemDescription;
+      this.allowedInputVariables = allowedInputVariables.ToArray();
+      var trainingRows = rows.ToArray();
+      this.kernel = (ICovarianceFunction)kernel.Clone();
+      this.lambda = lambda;
+      try {
+        if (scaleInputs)
+          scaling = CreateScaling(dataset, trainingRows);
+        trainX = ExtractData(dataset, trainingRows, scaling);
+        var y = dataset.GetDoubleValues(targetVariable, trainingRows).ToArray();
+        yOffset = y.Average();
+        yScale = 1.0 / y.StandardDeviation();
+        for (int i = 0; i < y.Length; i++) {
+          y[i] -= yOffset;
+          y[i] *= yScale;
+        }
+        int info;
+        int n = trainX.GetLength(0);
+        alglib.densesolverreport denseSolveRep;
+        var gram = BuildGramMatrix(trainX, lambda);
+        var l = new double[n, n]; Array.Copy(gram, l, l.Length);
+
+        double[,] invG;
+        // cholesky decomposition
+        var res = alglib.trfac.spdmatrixcholesky(ref l, n, false);
+        if (res == false) { //throw new ArgumentException("Could not decompose matrix. Is it quadratic symmetric positive definite?");
+          int[] pivots;
+          var lua = new double[n, n];
+          Array.Copy(gram, lua, lua.Length);
+          alglib.rmatrixlu(ref lua, n, n, out pivots);
+          alglib.rmatrixlusolve(lua, pivots, n, y, out info, out denseSolveRep, out alpha);
+          if (info != 1) throw new ArgumentException("Could not create model.");
+          alglib.matinvreport rep;
+          invG = lua;  // rename
+          alglib.rmatrixluinverse(ref invG, pivots, n, out info, out rep);
+          if (info != 1) throw new ArgumentException("Could not invert Gram matrix.");
+        } else {
+          alglib.spdmatrixcholeskysolve(l, n, false, y, out info, out denseSolveRep, out alpha);
+          if (info != 1) throw new ArgumentException("Could not create model.");
+          // for LOO-CV we need to build the inverse of the gram matrix
+          alglib.matinvreport rep;
+          invG = l;   // rename 
+          alglib.spdmatrixcholeskyinverse(ref invG, n, false, out info, out rep);
+          if (info != 1) throw new ArgumentException("Could not invert Gram matrix.");
+        }
+
+        var ssqLooError = 0.0;
+        for (int i = 0; i < n; i++) {
+          var pred_i = Util.ScalarProd(Util.GetRow(gram, i).ToArray(), alpha);
+          var looPred_i = pred_i - alpha[i] / invG[i, i];
+          var error = (y[i] - looPred_i) / yScale;
+          ssqLooError += error * error;
+        }
+        LooCvRMSE = Math.Sqrt(ssqLooError / n);
+      } catch (alglib.alglibexception ae) {
+        // wrap exception so that calling code doesn't have to know about alglib implementation
+        throw new ArgumentException("There was a problem in the calculation of the kernel ridge regression model", ae);
+      }
+    }
+
+
+    #region IRegressionModel Members
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      var newX = ExtractData(dataset, rows, scaling);
+      var dim = newX.GetLength(1);
+      var cov = kernel.GetParameterizedCovarianceFunction(new double[0], Enumerable.Range(0, dim).ToArray());
+
+      var pred = new double[newX.GetLength(0)];
+      for (int i = 0; i < pred.Length; i++) {
+        double sum = 0.0;
+        for (int j = 0; j < alpha.Length; j++) {
+          sum += alpha[j] * cov.CrossCovariance(trainX, newX, j, i);
+        }
+        pred[i] = sum / yScale + yOffset;
+      }
+      return pred;
+    }
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, new RegressionProblemData(problemData));
+    }
+    #endregion
+
+    #region helpers
+    private double[,] BuildGramMatrix(double[,] data, double lambda) {
+      var n = data.GetLength(0);
+      var dim = data.GetLength(1);
+      var cov = kernel.GetParameterizedCovarianceFunction(new double[0], Enumerable.Range(0, dim).ToArray());
+      var gram = new double[n, n];
+      // G = (K + λ I) 
+      for (var i = 0; i < n; i++) {
+        for (var j = i; j < n; j++) {
+          gram[i, j] = gram[j, i] = cov.Covariance(data, i, j); // symmetric matrix 
+        }
+        gram[i, i] += lambda;
+      }
+      return gram;
+    }
+
+    private ITransformation<double>[] CreateScaling(IDataset dataset, int[] rows) {
+      var trans = new ITransformation<double>[allowedInputVariables.Length];
+      int i = 0;
+      foreach (var variable in allowedInputVariables) {
+        var lin = new LinearTransformation(allowedInputVariables);
+        var max = dataset.GetDoubleValues(variable, rows).Max();
+        var min = dataset.GetDoubleValues(variable, rows).Min();
+        lin.Multiplier = 1.0 / (max - min);
+        lin.Addend = -min / (max - min);
+        trans[i] = lin;
+        i++;
+      }
+      return trans;
+    }
+
+    private double[,] ExtractData(IDataset dataset, IEnumerable<int> rows, ITransformation<double>[] scaling = null) {
+      double[][] variables;
+      if (scaling != null) {
+        variables =
+          allowedInputVariables.Select((var, i) => scaling[i].Apply(dataset.GetDoubleValues(var, rows)).ToArray())
+            .ToArray();
+      } else {
+        variables =
+        allowedInputVariables.Select(var => dataset.GetDoubleValues(var, rows).ToArray()).ToArray();
+      }
+      int n = variables.First().Length;
+      var res = new double[n, variables.Length];
+      for (int r = 0; r < n; r++)
+        for (int c = 0; c < variables.Length; c++) {
+          res[r, c] = variables[c][r];
+        }
+      return res;
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DistanceBase.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DistanceBase.cs	(revision 14904)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/DistanceBase.cs	(revision 14911)
@@ -20,4 +20,5 @@
 #endregion
 
+using System.Collections;
 using System.Collections.Generic;
 using HeuristicLab.Common;
@@ -42,5 +43,14 @@
     }
 
-    private class DistanceComparer : IComparer<T> {
+
+    public double Get(object x, object y) {
+      return Get((T)x, (T)y);
+    }
+
+    public IComparer GetDistanceComparer(object item) {
+      return new DistanceComparer((T)item, this);
+    }
+
+    private class DistanceComparer : IComparer<T>, IComparer {
       private readonly T item;
       private readonly IDistance<T> dist;
@@ -54,4 +64,8 @@
         return dist.Get(x, item).CompareTo(dist.Get(y, item));
       }
+
+      public int Compare(object x, object y) {
+        return Compare((T)x, (T)y);
+      }
     }
   }
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/ManhattanDistance.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/ManhattanDistance.cs	(revision 14911)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Distances/ManhattanDistance.cs	(revision 14911)
@@ -0,0 +1,56 @@
+﻿#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  [Item("ManhattanDistance", "A distance function that uses block distance")]
+  public class ManhattanDistance : DistanceBase<IEnumerable<double>> {
+
+    #region HLConstructors & Boilerplate
+    [StorableConstructor]
+    protected ManhattanDistance(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() { }
+    protected ManhattanDistance(ManhattanDistance original, Cloner cloner)
+      : base(original, cloner) { }
+    public ManhattanDistance() { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ManhattanDistance(this, cloner);
+    }
+    #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");
+      return point1.Zip(point2, (a1, b1) => Math.Abs(a1 - b1)).Sum();
+    }
+
+    public override double Get(IEnumerable<double> a, IEnumerable<double> b) {
+      return GetDistance(a.ToArray(), b.ToArray());
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Interfaces/IDistance.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Interfaces/IDistance.cs	(revision 14904)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/Interfaces/IDistance.cs	(revision 14911)
@@ -20,9 +20,10 @@
 #endregion
 
+using System.Collections;
 using System.Collections.Generic;
 using HeuristicLab.Core;
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
-  public interface IDistance<in T> : IItem {
+  public interface IDistance<in T> : IItem, IDistance {
     /// <summary>
     /// Calculates a distance measure between two objects.
@@ -41,3 +42,9 @@
     IComparer<T> GetDistanceComparer(T item);
   }
+
+
+  public interface IDistance : IItem {
+    double Get(object x, object y);
+    IComparer GetDistanceComparer(object item);
+  }
 }
