inverse_pow_dist_kernel_aux.h

00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00032 #ifndef INVERSE_POW_DIST_KERNEL_AUX_H
00033 #define INVERSE_POW_DIST_KERNEL_AUX_H
00034 
00035 #include "inverse_pow_dist_kernel.h"
00036 
00040 class InversePowDistGradientKernelAux {
00041 
00042  private:
00043 
00044   void SubFrom_(index_t dimension, int decrement,
00045                 const ArrayList<int> &subtract_from, 
00046                 ArrayList<int> &result) const {
00047     
00048     for(index_t d = 0; d < subtract_from.size(); d++) {
00049       if(d == dimension) {
00050         result[d] = subtract_from[d] - decrement;
00051       }
00052       else {
00053         result[d] = subtract_from[d];
00054       }
00055     }
00056   }
00057 
00058  public:
00059   
00060   typedef InversePowDistGradientKernel TKernel;
00061   
00062   typedef SeriesExpansionAux TSeriesExpansionAux;
00063   
00064   typedef FarFieldExpansion<InversePowDistGradientKernelAux> TFarFieldExpansion;
00065 
00066   typedef LocalExpansion<InversePowDistGradientKernelAux> TLocalExpansion;
00067 
00070   TKernel kernel_;
00071   
00074   TSeriesExpansionAux sea_;
00075 
00076   OT_DEF_BASIC(InversePowDistGradientKernelAux) {
00077     OT_MY_OBJECT(kernel_);
00078     OT_MY_OBJECT(sea_);
00079   }
00080 
00081  public:
00082 
00083   void Init(double bandwidth, int max_order, int dim) {
00084     kernel_.Init(bandwidth, dim);
00085     sea_.Init(max_order, dim);
00086   }
00087 
00088   void AllocateDerivativeMap(int dim, int order, 
00089                              Matrix *derivative_map) const {
00090     derivative_map->Init(sea_.get_total_num_coeffs(order), 1);
00091   }
00092 
00093   void ComputeDirectionalDerivatives(const Vector &x, 
00094                                      Matrix *derivative_map, int order) const {
00095 
00096     derivative_map->SetZero();
00097 
00098     // Squared L2 norm of the vector.
00099     double squared_l2_norm = la::Dot(x, x);
00100 
00101     // Temporary variable to look for arithmetic operations on
00102     // multiindex.
00103     ArrayList<int> tmp_multiindex;
00104     tmp_multiindex.Init(sea_.get_dimension());
00105 
00106     for(index_t i = 0; i < derivative_map->n_rows(); i++) {
00107     
00108       // Contribution to the current multiindex position.
00109       double contribution = 0;
00110 
00111       // Retrieve the multiindex mapping.
00112       const ArrayList<int> &multiindex = sea_.get_multiindex(i);
00113       
00114       // $D_{x}^{0} \phi_{\nu, d}(x)$ should be computed normally.
00115       if(i == 0) {
00116         derivative_map->set(0, 0, kernel_.EvalUnnorm(x.ptr()));
00117         continue;
00118       }
00119 
00120       // Compute the contribution of $D_{x}^{n - e_d} \phi_{\nu,
00121       // d}(x)$ component for each $d$.
00122       for(index_t d = 0; d < x.length(); d++) {
00123         
00124         // Subtract 1 from the given dimension.
00125         SubFrom_(d, 1, multiindex, tmp_multiindex);
00126         index_t n_minus_e_d_position = 
00127           sea_.ComputeMultiindexPosition(tmp_multiindex);
00128         if(n_minus_e_d_position >= 0) {
00129           double factor = 2 * multiindex[d] * x[d];
00130           if((kernel_.dimension_ == 0 && d == 1) ||
00131              (kernel_.dimension_ > 0 && d == 0)) {
00132             factor += (kernel_.lambda_ - 2);
00133           }
00134           contribution += factor * 
00135             derivative_map->get(n_minus_e_d_position, 0);
00136         }
00137         
00138         // Subtract 2 from the given dimension.
00139         SubFrom_(d, 2, multiindex, tmp_multiindex);
00140         index_t n_minus_two_e_d_position =
00141           sea_.ComputeMultiindexPosition(tmp_multiindex);
00142         if(n_minus_two_e_d_position >= 0) {
00143           double factor = multiindex[d] * (multiindex[d] - 1);
00144 
00145           if((kernel_.dimension_ == 0 && d == 1) ||
00146              (kernel_.dimension_ > 0 && d == 0)) {
00147             factor += (kernel_.lambda_ - 2) * (multiindex[d] - 1);
00148           }
00149 
00150           contribution += factor *
00151             derivative_map->get(n_minus_two_e_d_position, 0);
00152         }
00153         
00154       } // end of iterating over each dimension.
00155       
00156       // Set the final contribution for this multiindex.
00157       derivative_map->set(i, 0, -contribution / squared_l2_norm);
00158       
00159     } // end of iterating over all required multiindex positions...
00160   }
00161   
00162   double ComputePartialDerivative(const Matrix &derivative_map,
00163                                   const ArrayList<int> &mapping) const {
00164     
00165     return derivative_map.get(sea_.ComputeMultiindexPosition(mapping), 0);
00166   }
00167 
00168 };
00169 
00173 class InversePowDistKernelAux {
00174 
00175  private:
00176   void SubFrom_(index_t dimension, int decrement,
00177                 const ArrayList<int> &subtract_from, 
00178                 ArrayList<int> &result) const {
00179     
00180     for(index_t d = 0; d < subtract_from.size(); d++) {
00181       if(d == dimension) {
00182         result[d] = subtract_from[d] - decrement;
00183       }
00184       else {
00185         result[d] = subtract_from[d];
00186       }
00187     }
00188   }
00189 
00190  public:
00191   
00192   typedef InversePowDistKernel TKernel;
00193   
00194   typedef SeriesExpansionAux TSeriesExpansionAux;
00195   
00196   typedef FarFieldExpansion<InversePowDistKernelAux> TFarFieldExpansion;
00197 
00198   typedef LocalExpansion<InversePowDistKernelAux> TLocalExpansion;
00199 
00202   TKernel kernel_;
00203   
00206   TSeriesExpansionAux sea_;
00207 
00209 
00210   void Init(double power, int max_order, int dim) {
00211     kernel_.Init(power, dim);
00212     sea_.Init(max_order, dim);
00213   }
00214 
00215   void AllocateDerivativeMap(int dim, int order, 
00216                              Matrix *derivative_map) const {
00217     derivative_map->Init(sea_.get_total_num_coeffs(order), 1);
00218   }
00219 
00220   void ComputeDirectionalDerivatives(const Vector &x, 
00221                                      Matrix *derivative_map, int order) const {
00222 
00223     derivative_map->SetZero();
00224 
00225     // Squared L2 norm of the vector.
00226     double squared_l2_norm = la::Dot(x, x);
00227 
00228     // Temporary variable to look for arithmetic operations on
00229     // multiindex.
00230     ArrayList<int> tmp_multiindex;
00231     tmp_multiindex.Init(sea_.get_dimension());
00232 
00233     // Get the inverse multiindex factorial factors.
00234     const Vector &inv_multiindex_factorials = 
00235       sea_.get_inv_multiindex_factorials();
00236 
00237     for(index_t i = 0; i < derivative_map->n_rows(); i++) {
00238     
00239       // Contribution to the current multiindex position.
00240       double contribution = 0;
00241 
00242       // Retrieve the multiindex mapping.
00243       const ArrayList<int> &multiindex = sea_.get_multiindex(i);
00244       
00245       // $D_{x}^{0} \phi_{\nu, d}(x)$ should be computed normally.
00246       if(i == 0) {
00247         derivative_map->set(0, 0, kernel_.EvalUnnorm(x.ptr()));
00248         continue;
00249       }
00250 
00251       // The sum of the indices.
00252       index_t sum_of_indices = 0;
00253       for(index_t d = 0; d < x.length(); d++) {
00254         sum_of_indices += multiindex[d];
00255       }
00256 
00257       // The first factor multiplied.
00258       double first_factor = 2 * sum_of_indices + kernel_.lambda_ - 2;
00259 
00260       // The second factor multilied.
00261       double second_factor = sum_of_indices + kernel_.lambda_ - 2;
00262 
00263       // Compute the contribution of $D_{x}^{n - e_d} \phi_{\nu,
00264       // d}(x)$ component for each $d$.
00265       for(index_t d = 0; d < x.length(); d++) {
00266         
00267         // Subtract 1 from the given dimension.
00268         SubFrom_(d, 1, multiindex, tmp_multiindex);
00269         index_t n_minus_e_d_position = 
00270           sea_.ComputeMultiindexPosition(tmp_multiindex);
00271         if(n_minus_e_d_position >= 0) {
00272           contribution += first_factor * x[d] *
00273             derivative_map->get(n_minus_e_d_position, 0) *
00274             inv_multiindex_factorials[n_minus_e_d_position];
00275         }
00276         
00277         // Subtract 2 from the given dimension.
00278         SubFrom_(d, 2, multiindex, tmp_multiindex);
00279         index_t n_minus_two_e_d_position =
00280           sea_.ComputeMultiindexPosition(tmp_multiindex);
00281         if(n_minus_two_e_d_position >= 0) {
00282           contribution += second_factor *
00283             derivative_map->get(n_minus_two_e_d_position, 0) *
00284             inv_multiindex_factorials[n_minus_two_e_d_position];
00285         }
00286         
00287       } // end of iterating over each dimension.
00288       
00289       // Set the final contribution for this multiindex.
00290       if(squared_l2_norm == 0) {
00291         derivative_map->set(i, 0, 0);
00292       }
00293       else {
00294         derivative_map->set(i, 0, -contribution / squared_l2_norm /
00295                             sum_of_indices / inv_multiindex_factorials[i]);
00296       }
00297 
00298     } // end of iterating over all required multiindex positions...
00299 
00300     // Iterate again, and invert the sum if the sum of the indices of
00301     // the current mapping is odd.
00302     for(index_t i = 1; i < derivative_map->n_rows(); i++) {
00303 
00304       // Retrieve the multiindex mapping.
00305       const ArrayList<int> &multiindex = sea_.get_multiindex(i);
00306 
00307       // The sum of the indices.
00308       index_t sum_of_indices = 0;
00309       for(index_t d = 0; d < x.length(); d++) {
00310         sum_of_indices += multiindex[d];
00311       }
00312 
00313       if(sum_of_indices % 2 == 1) {
00314         derivative_map->set(i, 0, -derivative_map->get(i, 0));
00315       }
00316     }
00317   }
00318   
00319   double ComputePartialDerivative(const Matrix &derivative_map,
00320                                   const ArrayList<int> &mapping) const {
00321     
00322     return derivative_map.get(sea_.ComputeMultiindexPosition(mapping), 0);
00323   }
00324 };
00325 
00326 #endif
Generated on Mon Jan 24 12:04:38 2011 for FASTlib by  doxygen 1.6.3