00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00099 double squared_l2_norm = la::Dot(x, x);
00100
00101
00102
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
00109 double contribution = 0;
00110
00111
00112 const ArrayList<int> &multiindex = sea_.get_multiindex(i);
00113
00114
00115 if(i == 0) {
00116 derivative_map->set(0, 0, kernel_.EvalUnnorm(x.ptr()));
00117 continue;
00118 }
00119
00120
00121
00122 for(index_t d = 0; d < x.length(); d++) {
00123
00124
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
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 }
00155
00156
00157 derivative_map->set(i, 0, -contribution / squared_l2_norm);
00158
00159 }
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
00226 double squared_l2_norm = la::Dot(x, x);
00227
00228
00229
00230 ArrayList<int> tmp_multiindex;
00231 tmp_multiindex.Init(sea_.get_dimension());
00232
00233
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
00240 double contribution = 0;
00241
00242
00243 const ArrayList<int> &multiindex = sea_.get_multiindex(i);
00244
00245
00246 if(i == 0) {
00247 derivative_map->set(0, 0, kernel_.EvalUnnorm(x.ptr()));
00248 continue;
00249 }
00250
00251
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
00258 double first_factor = 2 * sum_of_indices + kernel_.lambda_ - 2;
00259
00260
00261 double second_factor = sum_of_indices + kernel_.lambda_ - 2;
00262
00263
00264
00265 for(index_t d = 0; d < x.length(); d++) {
00266
00267
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
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 }
00288
00289
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 }
00299
00300
00301
00302 for(index_t i = 1; i < derivative_map->n_rows(); i++) {
00303
00304
00305 const ArrayList<int> &multiindex = sea_.get_multiindex(i);
00306
00307
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