[mlpack-git] master: Take different types for each kernel and metric argument. (3e7d8bc)

gitdub at big.cc.gt.atl.ga.us gitdub at big.cc.gt.atl.ga.us
Sun Apr 5 18:48:23 EDT 2015


Repository : https://github.com/mlpack/mlpack

On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/c41bc8d54695f1a20b3de551bc80fe7221dd3cd1...81fe638aa0c8d9592bbf7b434110140eb9bb86e7

>---------------------------------------------------------------

commit 3e7d8bc2bb681686ca5b731ebeb0500e0327335d
Author: ryan <ryan at ratml.org>
Date:   Fri Apr 3 17:18:50 2015 -0400

    Take different types for each kernel and metric argument.


>---------------------------------------------------------------

3e7d8bc2bb681686ca5b731ebeb0500e0327335d
 src/mlpack/core/kernels/cosine_distance.hpp        |  4 +-
 src/mlpack/core/kernels/cosine_distance_impl.hpp   |  4 +-
 src/mlpack/core/kernels/epanechnikov_kernel.hpp    | 13 ++---
 .../core/kernels/epanechnikov_kernel_impl.hpp      | 16 +++---
 src/mlpack/core/kernels/example_kernel.hpp         | 18 ++++---
 src/mlpack/core/kernels/gaussian_kernel.hpp        | 16 +++---
 .../core/kernels/hyperbolic_tangent_kernel.hpp     |  8 +--
 src/mlpack/core/kernels/laplacian_kernel.hpp       |  9 ++--
 src/mlpack/core/kernels/linear_kernel.hpp          |  8 +--
 src/mlpack/core/kernels/polynomial_kernel.hpp      |  8 +--
 src/mlpack/core/kernels/spherical_kernel.hpp       | 62 ++++++++++++++--------
 src/mlpack/core/kernels/triangular_kernel.hpp      |  6 ++-
 src/mlpack/core/metrics/ip_metric.hpp              | 28 ++++++++--
 src/mlpack/core/metrics/lmetric.hpp                | 15 ++++--
 src/mlpack/core/metrics/lmetric_impl.hpp           | 34 ++++++------
 src/mlpack/core/metrics/mahalanobis_distance.hpp   | 10 ++--
 .../core/metrics/mahalanobis_distance_impl.hpp     | 12 ++---
 17 files changed, 164 insertions(+), 107 deletions(-)

diff --git a/src/mlpack/core/kernels/cosine_distance.hpp b/src/mlpack/core/kernels/cosine_distance.hpp
index d2a6fea..77c8142 100644
--- a/src/mlpack/core/kernels/cosine_distance.hpp
+++ b/src/mlpack/core/kernels/cosine_distance.hpp
@@ -32,8 +32,8 @@ class CosineDistance
    * @param b Second vector.
    * @return d(a, b).
    */
-  template<typename VecType>
-  static double Evaluate(const VecType& a, const VecType& b);
+  template<typename VecTypeA, typename VecTypeB>
+  static double Evaluate(const VecTypeA& a, const VecTypeB& b);
 
   /**
    * Returns a string representation of this object.
diff --git a/src/mlpack/core/kernels/cosine_distance_impl.hpp b/src/mlpack/core/kernels/cosine_distance_impl.hpp
index 69a1a3e..870691a 100644
--- a/src/mlpack/core/kernels/cosine_distance_impl.hpp
+++ b/src/mlpack/core/kernels/cosine_distance_impl.hpp
@@ -12,8 +12,8 @@
 namespace mlpack {
 namespace kernel {
 
-template<typename VecType>
-double CosineDistance::Evaluate(const VecType& a, const VecType& b)
+template<typename VecTypeA, typename VecTypeB>
+double CosineDistance::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   // Since we are using the L2 inner product, this is easy.  But we have to make
   // sure we aren't dividing by zero (if we are, then the cosine similarity is
diff --git a/src/mlpack/core/kernels/epanechnikov_kernel.hpp b/src/mlpack/core/kernels/epanechnikov_kernel.hpp
index c47bd43..4db40c6 100644
--- a/src/mlpack/core/kernels/epanechnikov_kernel.hpp
+++ b/src/mlpack/core/kernels/epanechnikov_kernel.hpp
@@ -37,11 +37,13 @@ class EpanechnikovKernel
   /**
    * Evaluate the Epanechnikov kernel on the given two inputs.
    *
+   * @tparam VecTypeA Type of first vector.
+   * @tparam VecTypeB Type of second vector.
    * @param a One input vector.
    * @param b The other input vector.
    */
-  template<typename Vec1Type, typename Vec2Type>
-  double Evaluate(const Vec1Type& a, const Vec2Type& b) const;
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b) const;
 
   /**
    * Evaluate the Epanechnikov kernel given that the distance between the two
@@ -58,9 +60,8 @@ class EpanechnikovKernel
    * @param b Second vector.
    * @return the convolution integral value.
    */
-
-  template<typename VecType>
-  double ConvolutionIntegral(const VecType& a, const VecType& b);
+  template<typename VecTypeA, typename VecTypeB>
+  double ConvolutionIntegral(const VecTypeA& a, const VecTypeB& b);
 
   /**
    * Compute the normalizer of this Epanechnikov kernel for the given dimension.
@@ -69,7 +70,7 @@ class EpanechnikovKernel
    */
   double Normalizer(const size_t dimension);
 
-  // Returns String of O bject
+  //! Returns string representation of object.
   std::string ToString() const;
 
  private:
diff --git a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp
index d1e5eb6..bd40bb2 100644
--- a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp
+++ b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp
@@ -15,28 +15,28 @@
 namespace mlpack {
 namespace kernel {
 
-template<typename Vec1Type, typename Vec2Type>
-inline double EpanechnikovKernel::Evaluate(const Vec1Type& a, const Vec2Type& b)
+template<typename VecTypeA, typename VecTypeB>
+inline double EpanechnikovKernel::Evaluate(const VecTypeA& a, const VecTypeB& b)
     const
 {
   return std::max(0.0, 1.0 - metric::SquaredEuclideanDistance::Evaluate(a, b)
       * inverseBandwidthSquared);
 }
 
-
-
 /**
  * Obtains the convolution integral [integral of K(||x-a||) K(||b-x||) dx]
  * for the two vectors.
  *
- * @tparam VecType Type of vector (arma::vec, arma::spvec should be expected).
+ * @tparam VecTypeA Type of first vector (arma::vec, arma::sp_vec should be
+ *      expected).
+ * @tparam VecTypeB Type of second vector (arma::vec, arma::sp_vec).
  * @param a First vector.
  * @param b Second vector.
  * @return the convolution integral value.
  */
-template<typename VecType>
-double EpanechnikovKernel::ConvolutionIntegral(const VecType& a,
-                                               const VecType& b)
+template<typename VecTypeA, typename VecTypeB>
+double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a,
+                                               const VecTypeB& b)
 {
   double distance = sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b));
   if (distance >= 2.0 * bandwidth)
diff --git a/src/mlpack/core/kernels/example_kernel.hpp b/src/mlpack/core/kernels/example_kernel.hpp
index d957e7c..46380ea 100644
--- a/src/mlpack/core/kernels/example_kernel.hpp
+++ b/src/mlpack/core/kernels/example_kernel.hpp
@@ -93,13 +93,15 @@ class ExampleKernel
    * function static.  For a more complex example which cannot be declared
    * static, see the GaussianKernel, which stores an internal parameter.
    *
-   * @tparam VecType Type of vector (arma::vec, arma::spvec should be expected).
+   * @tparam VecTypeA Type of first vector (arma::vec, arma::sp_vec should be
+   *      expected).
+   * @tparam VecTypeB Type of second vector (arma::vec, arma::sp_vec).
    * @param a First vector.
    * @param b Second vector.
    * @return K(a, b).
    */
-  template<typename VecType>
-  static double Evaluate(const VecType& /* a */, const VecType& /* b */)
+  template<typename VecTypeA, typename VecTypeB>
+  static double Evaluate(const VecTypeA& /* a */, const VecTypeB& /* b */)
   { return 0; }
 
   /**
@@ -121,14 +123,16 @@ class ExampleKernel
    * function static.  For a more complex example which cannot be declared
    * static, see the GaussianKernel, which stores an internal parameter.
    *
-   * @tparam VecType Type of vector (arma::vec, arma::spvec should be expected).
+   * @tparam VecTypeA Type of first vector (arma::vec, arma::sp_vec should be
+   *      expected).
+   * @tparam VecTypeB Type of second vector (arma::vec, arma::sp_vec).
    * @param a First vector.
    * @param b Second vector.
    * @return the convolution integral value.
    */
-  template<typename VecType>
-  static double ConvolutionIntegral(const VecType& /* a */,
-                                    const VecType& /* b */) { return 0; }
+  template<typename VecTypeA, typename VecTypeB>
+  static double ConvolutionIntegral(const VecTypeA& /* a */,
+                                    const VecTypeB& /* b */) { return 0; }
 
   /**
    * Obtains the normalizing volume for the kernel with dimension $dimension$.
diff --git a/src/mlpack/core/kernels/gaussian_kernel.hpp b/src/mlpack/core/kernels/gaussian_kernel.hpp
index 859a91d..9e52638 100644
--- a/src/mlpack/core/kernels/gaussian_kernel.hpp
+++ b/src/mlpack/core/kernels/gaussian_kernel.hpp
@@ -55,8 +55,8 @@ class GaussianKernel
    * @return K(a, b) using the bandwidth (@f$\mu at f$) specified in the
    *   constructor.
    */
-  template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b) const
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b) const
   {
     // The precalculation of gamma saves us a little computation time.
     return exp(gamma * metric::SquaredEuclideanDistance::Evaluate(a, b));
@@ -89,15 +89,15 @@ class GaussianKernel
   /**
    * Obtain a convolution integral of the Gaussian kernel.
    *
-   * @param a, first vector
-   * @param b, second vector
-   * @return the convolution integral
+   * @param a First vector.
+   * @param b Second vector.
+   * @return The convolution integral.
    */
-  template<typename VecType>
-  double ConvolutionIntegral(const VecType& a, const VecType& b)
+  template<typename VecTypeA, typename VecTypeB>
+  double ConvolutionIntegral(const VecTypeA& a, const VecTypeB& b)
   {
     return Evaluate(sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b) / 2.0)) /
-      (Normalizer(a.n_rows) * pow(2.0, (double) a.n_rows / 2.0));
+        (Normalizer(a.n_rows) * pow(2.0, (double) a.n_rows / 2.0));
   }
 
 
diff --git a/src/mlpack/core/kernels/hyperbolic_tangent_kernel.hpp b/src/mlpack/core/kernels/hyperbolic_tangent_kernel.hpp
index 77fb4e7..7ebd41c 100644
--- a/src/mlpack/core/kernels/hyperbolic_tangent_kernel.hpp
+++ b/src/mlpack/core/kernels/hyperbolic_tangent_kernel.hpp
@@ -44,13 +44,15 @@ class HyperbolicTangentKernel
    * Evaluate the hyperbolic tangent kernel.  This evaluation uses Armadillo's
    * dot() function.
    *
-   * @tparam VecType Type of vector (should be arma::vec or arma::spvec).
+   * @tparam VecTypeA Type of first vector (should be arma::vec or
+   *      arma::sp_vec).
+   * @tparam VecTypeB Type of second vector (arma::vec / arma::sp_vec).
    * @param a First vector.
    * @param b Second vector.
    * @return K(a, b).
    */
-  template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b)
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b)
   {
     return tanh(scale * arma::dot(a, b) + offset);
   }
diff --git a/src/mlpack/core/kernels/laplacian_kernel.hpp b/src/mlpack/core/kernels/laplacian_kernel.hpp
index 65f99a3..bb865ef 100644
--- a/src/mlpack/core/kernels/laplacian_kernel.hpp
+++ b/src/mlpack/core/kernels/laplacian_kernel.hpp
@@ -45,14 +45,15 @@ class LaplacianKernel
    * distance metric, not the Euclidean distance, but for now, the Euclidean
    * distance is used.
    *
-   * @tparam VecType Type of vector (likely arma::vec or arma::spvec).
+   * @tparam VecTypeA Type of first vector (likely arma::vec or arma::sp_vec).
+   * @tparam VecTypeB Type of second vector (arma::vec / arma::sp_vec).
    * @param a First vector.
    * @param b Second vector.
    * @return K(a, b) using the bandwidth (@f$\mu at f$) specified in the
-   *   constructor.
+   *      constructor.
    */
-  template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b) const
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b) const
   {
     // The precalculation of gamma saves us a little computation time.
     return exp(-metric::EuclideanDistance::Evaluate(a, b) / bandwidth);
diff --git a/src/mlpack/core/kernels/linear_kernel.hpp b/src/mlpack/core/kernels/linear_kernel.hpp
index 6dfbfba..26c098e 100644
--- a/src/mlpack/core/kernels/linear_kernel.hpp
+++ b/src/mlpack/core/kernels/linear_kernel.hpp
@@ -37,13 +37,15 @@ class LinearKernel
    * Simple evaluation of the dot product.  This evaluation uses Armadillo's
    * dot() function.
    *
-   * @tparam VecType Type of vector (should be arma::vec or arma::spvec).
+   * @tparam VecTypeA Type of first vector (should be arma::vec or
+   *      arma::sp_vec).
+   * @tparam VecTypeB Type of second vector (arma::vec / arma::sp_vec).
    * @param a First vector.
    * @param b Second vector.
    * @return K(a, b).
    */
-  template<typename VecType>
-  static double Evaluate(const VecType& a, const VecType& b)
+  template<typename VecTypeA, typename VecTypeB>
+  static double Evaluate(const VecTypeA& a, const VecTypeB& b)
   {
     return arma::dot(a, b);
   }
diff --git a/src/mlpack/core/kernels/polynomial_kernel.hpp b/src/mlpack/core/kernels/polynomial_kernel.hpp
index ca0eff6..b64f133 100644
--- a/src/mlpack/core/kernels/polynomial_kernel.hpp
+++ b/src/mlpack/core/kernels/polynomial_kernel.hpp
@@ -39,13 +39,15 @@ class PolynomialKernel
    * Simple evaluation of the dot product.  This evaluation uses Armadillo's
    * dot() function.
    *
-   * @tparam VecType Type of vector (should be arma::vec or arma::spvec).
+   * @tparam VecTypeA Type of first vector (should be arma::vec or
+   *      arma::sp_vec).
+   * @tparam VecTypeB Type of second vector (arma::vec / arma::sp_vec).
    * @param a First vector.
    * @param b Second vector.
    * @return K(a, b).
    */
-  template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b) const
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b) const
   {
     return pow((arma::dot(a, b) + offset), degree);
   }
diff --git a/src/mlpack/core/kernels/spherical_kernel.hpp b/src/mlpack/core/kernels/spherical_kernel.hpp
index faf355c..d8e04f8 100644
--- a/src/mlpack/core/kernels/spherical_kernel.hpp
+++ b/src/mlpack/core/kernels/spherical_kernel.hpp
@@ -1,12 +1,9 @@
 /**
  * @file spherical_kernel.hpp
  * @author Neil Slagle
- *
- * This is an example kernel.  If you are making your own kernel, follow the
- * outline specified in this file.
  */
-#ifndef __MLPACK_CORE_KERNELS_SPHERICAL_KERNEL_H
-#define __MLPACK_CORE_KERNELS_SPHERICAL_KERNEL_H
+#ifndef __MLPACK_CORE_KERNELS_SPHERICAL_KERNEL_HPP
+#define __MLPACK_CORE_KERNELS_SPHERICAL_KERNEL_HPP
 
 #include <boost/math/special_functions/gamma.hpp>
 #include <mlpack/core.hpp>
@@ -14,37 +11,50 @@
 namespace mlpack {
 namespace kernel {
 
+/**
+ * The spherical kernel, which is 1 when the distance between the two argument
+ * points is less than or equal to the bandwidth, or 0 otherwise.
+ */
 class SphericalKernel
 {
  public:
-  SphericalKernel() :
-    bandwidth(1.0),
-    bandwidthSquared(1.0) {}
-  SphericalKernel(double b) :
-    bandwidth(b),
-    bandwidthSquared(b*b) {}
+  /**
+   * Construct the SphericalKernel with the given bandwidth.
+   */
+  SphericalKernel(const double bandwidth = 1.0) :
+    bandwidth(bandwidth),
+    bandwidthSquared(std::pow(bandwidth, 2.0))
+  { /* Nothing to do. */ }
 
-  template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b)
+  /**
+   * Evaluate the spherical kernel with the given two vectors.
+   *
+   * @tparam VecTypeA Type of first vector.
+   * @tparam VecTypeB Type of second vector.
+   * @param a First vector.
+   * @param b Second vector.
+   * @return The kernel evaluation between the two vectors.
+   */
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b) const
   {
     return
-      (metric::SquaredEuclideanDistance::Evaluate(a, b) <= bandwidthSquared) ?
+        (metric::SquaredEuclideanDistance::Evaluate(a, b) <= bandwidthSquared) ?
         1.0 : 0.0;
   }
   /**
    * Obtains the convolution integral [integral K(||x-a||)K(||b-x||)dx]
-   * for the two vectors.  In this case, because
-   * our simple example kernel has no internal parameters, we can declare the
-   * function static.  For a more complex example which cannot be declared
-   * static, see the GaussianKernel, which stores an internal parameter.
+   * for the two vectors.
    *
-   * @tparam VecType Type of vector (arma::vec, arma::spvec should be expected).
+   * @tparam VecTypeA Type of first vector (arma::vec, arma::sp_vec should be
+   *       expected).
+   * @tparam VecTypeB Type of second vector.
    * @param a First vector.
    * @param b Second vector.
    * @return the convolution integral value.
    */
-  template<typename VecType>
-  double ConvolutionIntegral(const VecType& a, const VecType& b)
+  template<typename VecTypeA, typename VecTypeB>
+  double ConvolutionIntegral(const VecTypeA& a, const VecTypeB& b) const
   {
     double distance = sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b));
     if (distance >= 2.0 * bandwidth)
@@ -70,12 +80,18 @@ class SphericalKernel
         break;
     }
   }
-  double Normalizer(size_t dimension)
+  double Normalizer(size_t dimension) const
   {
     return pow(bandwidth, (double) dimension) * pow(M_PI, dimension / 2.0) /
         boost::math::tgamma(dimension / 2.0 + 1.0);
   }
-  double Evaluate(double t)
+
+  /**
+   * Evaluate the kernel when only a distance is given, not two points.
+   *
+   * @param t Argument to kernel.
+   */
+  double Evaluate(const double t) const
   {
     return (t <= bandwidth) ? 1.0 : 0.0;
   }
diff --git a/src/mlpack/core/kernels/triangular_kernel.hpp b/src/mlpack/core/kernels/triangular_kernel.hpp
index e724c76..7b8020a 100644
--- a/src/mlpack/core/kernels/triangular_kernel.hpp
+++ b/src/mlpack/core/kernels/triangular_kernel.hpp
@@ -35,11 +35,13 @@ class TriangularKernel
   /**
    * Evaluate the triangular kernel for the two given vectors.
    *
+   * @tparam VecTypeA Type of first vector.
+   * @tparam VecTypeB Type of second vector.
    * @param a First vector.
    * @param b Second vector.
    */
-  template<typename Vec1Type, typename Vec2Type>
-  double Evaluate(const Vec1Type& a, const Vec2Type& b) const
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b) const
   {
     return std::max(0.0, (1 - metric::EuclideanDistance::Evaluate(a, b) /
         bandwidth));
diff --git a/src/mlpack/core/metrics/ip_metric.hpp b/src/mlpack/core/metrics/ip_metric.hpp
index af87177..c8d97df 100644
--- a/src/mlpack/core/metrics/ip_metric.hpp
+++ b/src/mlpack/core/metrics/ip_metric.hpp
@@ -11,6 +11,18 @@
 namespace mlpack {
 namespace metric {
 
+/**
+ * The inner product metric, IPMetric, takes a given Mercer kernel (KernelType),
+ * and when Evaluate() is called, returns the distance between the two points in
+ * kernel space:
+ *
+ * @f[
+ * d(x, y) = \sqrt{ K(x, x) + K(y, y) - 2K(x, y) }.
+ * @f]
+ *
+ * @tparam KernelType Type of Kernel to use.  This must be a Mercer kernel
+ *     (positive definite), otherwise the metric may not be valid.
+ */
 template<typename KernelType>
 class IPMetric
 {
@@ -26,18 +38,24 @@ class IPMetric
 
   /**
    * Evaluate the metric.
+   *
+   * @tparam VecTypeA Type of first vector.
+   * @tparam VecTypeB Type of second vector.
+   * @param a First vector.
+   * @param b Second vector.
+   * @return Distance between the two points in kernel space.
    */
-  template<typename Vec1Type, typename Vec2Type>
-  double Evaluate(const Vec1Type& a, const Vec2Type& b);
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b);
 
   //! Get the kernel.
   const KernelType& Kernel() const { return kernel; }
   //! Modify the kernel.
   KernelType& Kernel() { return kernel; }
-  /**
-   * Returns a string representation of this object.
-   */
+
+  //! Returns a string representation of this object.
   std::string ToString() const;
+
  private:
   //! The locally stored kernel, if it is necessary.
   KernelType* localKernel;
diff --git a/src/mlpack/core/metrics/lmetric.hpp b/src/mlpack/core/metrics/lmetric.hpp
index 8ac655d..25f19fa 100644
--- a/src/mlpack/core/metrics/lmetric.hpp
+++ b/src/mlpack/core/metrics/lmetric.hpp
@@ -59,16 +59,25 @@ class LMetric
 {
  public:
   /***
-   * Default constructor does nothing, but is required to satisfy the Kernel
+   * Default constructor does nothing, but is required to satisfy the Metric
    * policy.
    */
   LMetric() { }
 
   /**
    * Computes the distance between two points.
+   *
+   * @tparam VecTypeA Type of first vector (generally arma::vec or
+   *      arma::sp_vec).
+   * @tparam VecTypeB Type of second vector.
+   * @param a First vector.
+   * @param b Second vector.
+   * @return Distance between vectors a and b.
    */
-  template<typename VecType1, typename VecType2>
-  static double Evaluate(const VecType1& a, const VecType2& b);
+  template<typename VecTypeA, typename VecTypeB>
+  static double Evaluate(const VecTypeA& a, const VecTypeB& b);
+
+  //! Return a string representation of the object.
   std::string ToString() const;
 };
 
diff --git a/src/mlpack/core/metrics/lmetric_impl.hpp b/src/mlpack/core/metrics/lmetric_impl.hpp
index 8cc81c5..7558a06 100644
--- a/src/mlpack/core/metrics/lmetric_impl.hpp
+++ b/src/mlpack/core/metrics/lmetric_impl.hpp
@@ -15,9 +15,9 @@ namespace metric {
 
 // Unspecialized implementation.  This should almost never be used...
 template<int Power, bool TakeRoot>
-template<typename VecType1, typename VecType2>
-double LMetric<Power, TakeRoot>::Evaluate(const VecType1& a,
-                                             const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<Power, TakeRoot>::Evaluate(const VecTypeA& a,
+                                          const VecTypeB& b)
 {
   double sum = 0;
   for (size_t i = 0; i < a.n_elem; i++)
@@ -42,38 +42,38 @@ std::string LMetric<Power, TakeRoot>::ToString() const
 
 // L1-metric specializations; the root doesn't matter.
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<1, true>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<1, true>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   return accu(abs(a - b));
 }
 
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<1, false>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<1, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   return accu(abs(a - b));
 }
 
 // L2-metric specializations.
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<2, true>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<2, true>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   return sqrt(accu(square(a - b)));
 }
 
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<2, false>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<2, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   return accu(square(a - b));
 }
 
 // L3-metric specialization (not very likely to be used, but just in case).
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<3, true>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<3, true>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   double sum = 0;
   for (size_t i = 0; i < a.n_elem; i++)
@@ -83,16 +83,16 @@ double LMetric<3, true>::Evaluate(const VecType1& a, const VecType2& b)
 }
 
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<3, false>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<3, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   return accu(pow(abs(a - b), 3.0));
 }
 
 // L-infinity (Chebyshev distance) specialization
 template<>
-template<typename VecType1, typename VecType2>
-double LMetric<INT_MAX, false>::Evaluate(const VecType1& a, const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double LMetric<INT_MAX, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
 {
   return arma::as_scalar(max(abs(a - b)));
 }
diff --git a/src/mlpack/core/metrics/mahalanobis_distance.hpp b/src/mlpack/core/metrics/mahalanobis_distance.hpp
index 23518dd..88bcca3 100644
--- a/src/mlpack/core/metrics/mahalanobis_distance.hpp
+++ b/src/mlpack/core/metrics/mahalanobis_distance.hpp
@@ -80,11 +80,8 @@ class MahalanobisDistance
    * @param a First vector.
    * @param b Second vector.
    */
-
-  // Return String of Object
-  std::string ToString() const;
-  template<typename VecType1, typename VecType2>
-  double Evaluate(const VecType1& a, const VecType2& b);
+  template<typename VecTypeA, typename VecTypeB>
+  double Evaluate(const VecTypeA& a, const VecTypeB& b);
 
   /**
    * Access the covariance matrix.
@@ -99,6 +96,9 @@ class MahalanobisDistance
    * @return Reference to the covariance matrix.
    */
   arma::mat& Covariance() { return covariance; }
+
+  //! Return string representation of object.
+  std::string ToString() const;
  private:
   //! The covariance matrix associated with this distance.
   arma::mat covariance;
diff --git a/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp b/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp
index 0175b7f..b9f9199 100644
--- a/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp
+++ b/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp
@@ -16,9 +16,9 @@ namespace metric {
  * Specialization for non-rooted case.
  */
 template<>
-template<typename VecType1, typename VecType2>
-double MahalanobisDistance<false>::Evaluate(const VecType1& a,
-                                            const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double MahalanobisDistance<false>::Evaluate(const VecTypeA& a,
+                                            const VecTypeB& b)
 {
   arma::vec m = (a - b);
   arma::mat out = trans(m) * covariance * m; // 1x1
@@ -29,9 +29,9 @@ double MahalanobisDistance<false>::Evaluate(const VecType1& a,
  * sqrt().
  */
 template<>
-template<typename VecType1, typename VecType2>
-double MahalanobisDistance<true>::Evaluate(const VecType1& a,
-                                           const VecType2& b)
+template<typename VecTypeA, typename VecTypeB>
+double MahalanobisDistance<true>::Evaluate(const VecTypeA& a,
+                                           const VecTypeB& b)
 {
   // Check if covariance matrix has been initialized.
   if (covariance.n_rows == 0)



More information about the mlpack-git mailing list