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
00042 #ifndef KERNEL_AUX
00043 #define KERNEL_AUX
00044
00045 #include "fastlib/fastlib.h"
00046
00047 #include "bounds_aux.h"
00048 #include "farfield_expansion.h"
00049 #include "local_expansion.h"
00050 #include "inverse_pow_dist_kernel_aux.h"
00051 #include "mult_farfield_expansion.h"
00052 #include "mult_local_expansion.h"
00053
00054
00059 class GaussianKernelMultAux {
00060
00061 public:
00062
00063 typedef GaussianKernel TKernel;
00064
00065 typedef MultSeriesExpansionAux TSeriesExpansionAux;
00066
00067 typedef MultFarFieldExpansion<GaussianKernelMultAux> TFarFieldExpansion;
00068
00069 typedef MultLocalExpansion<GaussianKernelMultAux> TLocalExpansion;
00070
00072 TKernel kernel_;
00073
00075 TSeriesExpansionAux sea_;
00076
00077 OT_DEF_BASIC(GaussianKernelMultAux) {
00078 OT_MY_OBJECT(kernel_);
00079 OT_MY_OBJECT(sea_);
00080 }
00081
00082 public:
00083
00084 void Init(double bandwidth, int max_order, int dim) {
00085 kernel_.Init(bandwidth);
00086 sea_.Init(max_order, dim);
00087 }
00088
00089 double BandwidthFactor(double bandwidth_sq) const {
00090 return sqrt(2 * bandwidth_sq);
00091 }
00092
00093 void AllocateDerivativeMap(int dim, int order,
00094 Matrix *derivative_map) const {
00095 derivative_map->Init(dim, order + 1);
00096 }
00097
00098 void ComputeDirectionalDerivatives(const Vector &x,
00099 Matrix *derivative_map, int order) const {
00100
00101 int dim = x.length();
00102
00103
00104 for(index_t d = 0; d < dim; d++) {
00105
00106 double coord_div_band = x[d];
00107 double d2 = 2 * coord_div_band;
00108 double facj = exp(-coord_div_band * coord_div_band);
00109
00110 derivative_map->set(d, 0, facj);
00111
00112 if(order > 0) {
00113
00114 derivative_map->set(d, 1, d2 * facj);
00115
00116 if(order > 1) {
00117 for(index_t k = 1; k < order; k++) {
00118 int k2 = k * 2;
00119 derivative_map->set(d, k + 1, d2 * derivative_map->get(d, k) -
00120 k2 * derivative_map->get(d, k - 1));
00121 }
00122 }
00123 }
00124 }
00125 }
00126
00127 double ComputePartialDerivative(const Matrix &derivative_map,
00128 const ArrayList<int> &mapping) const {
00129
00130 double partial_derivative = 1.0;
00131
00132 for(index_t d = 0; d < mapping.size(); d++) {
00133 partial_derivative *= derivative_map.get(d, mapping[d]);
00134 }
00135 return partial_derivative;
00136 }
00137
00138 template<typename TBound>
00139 int OrderForEvaluatingFarField
00140 (const TBound &far_field_region, const TBound &local_field_region,
00141 double min_dist_sqd_regions, double max_dist_sqd_regions,
00142 double max_error, double *actual_error) const {
00143
00144
00145
00146 double max_far_field_length =
00147 bounds_aux::MaxSideLengthOfBoundingBox(far_field_region);
00148
00149 double two_times_bandwidth = sqrt(kernel_.bandwidth_sq()) * 2;
00150 double r = max_far_field_length / two_times_bandwidth;
00151
00152 int dim = sea_.get_dimension();
00153 double r_raised_to_p_alpha = 1.0;
00154 double ret, ret2;
00155 int p_alpha = 0;
00156 double factorialvalue = 1.0;
00157 double first_factor, second_factor;
00158 double one_minus_r;
00159
00160
00161 if(r >= 1.0) {
00162 return -1;
00163 }
00164 one_minus_r = 1.0 - r;
00165 ret = 1.0 / pow(one_minus_r, dim);
00166
00167 do {
00168 factorialvalue *= (p_alpha + 1);
00169
00170 if(factorialvalue < 0.0 || p_alpha > sea_.get_max_order()) {
00171 return -1;
00172 }
00173
00174 r_raised_to_p_alpha *= r;
00175 first_factor = 1.0 - r_raised_to_p_alpha;
00176 second_factor = r_raised_to_p_alpha / sqrt(factorialvalue);
00177
00178 ret2 = ret * (pow((first_factor + second_factor), dim) -
00179 pow(first_factor, dim));
00180
00181 if(ret2 <= max_error) {
00182 break;
00183 }
00184
00185 p_alpha++;
00186
00187 } while(1);
00188
00189 *actual_error = ret2;
00190 return p_alpha;
00191 }
00192
00193 template<typename TBound>
00194 int OrderForConvertingFromFarFieldToLocal
00195 (const TBound &far_field_region,
00196 const TBound &local_field_region, double min_dist_sqd_regions,
00197 double max_dist_sqd_regions, double max_error,
00198 double *actual_error) const {
00199
00200
00201
00202 double max_far_field_length =
00203 bounds_aux::MaxSideLengthOfBoundingBox(far_field_region);
00204 double max_local_field_length =
00205 bounds_aux::MaxSideLengthOfBoundingBox(local_field_region);
00206
00207 double two_times_bandwidth = sqrt(kernel_.bandwidth_sq()) * 2;
00208 double r = max_far_field_length / two_times_bandwidth;
00209 double r2 = max_local_field_length / two_times_bandwidth;
00210
00211 int dim = sea_.get_dimension();
00212 double r_raised_to_p_alpha = 1.0;
00213 double ret, ret2;
00214 int p_alpha = 0;
00215 double factorialvalue = 1.0;
00216 double first_factor, second_factor;
00217 double one_minus_two_r, two_r;
00218
00219
00220 if(r >= 0.5 || r2 >= 0.5) {
00221 return -1;
00222 }
00223
00224 r = max(r, r2);
00225 two_r = 2.0 * r;
00226 one_minus_two_r = 1.0 - two_r;
00227 ret = 1.0 / pow(one_minus_two_r * one_minus_two_r, dim);
00228
00229 do {
00230 factorialvalue *= (p_alpha + 1);
00231
00232 if(factorialvalue < 0.0 || p_alpha > sea_.get_max_order()) {
00233 return -1;
00234 }
00235
00236 r_raised_to_p_alpha *= two_r;
00237 first_factor = 1.0 - r_raised_to_p_alpha;
00238 first_factor *= first_factor;
00239 second_factor = r_raised_to_p_alpha * (2.0 - r_raised_to_p_alpha)
00240 / sqrt(factorialvalue);
00241
00242 ret2 = ret * (pow((first_factor + second_factor), dim) -
00243 pow(first_factor, dim));
00244
00245 if(ret2 <= max_error) {
00246 break;
00247 }
00248
00249 p_alpha++;
00250
00251 } while(1);
00252
00253 *actual_error = ret2;
00254 return p_alpha;
00255 }
00256
00257 template<typename TBound>
00258 int OrderForEvaluatingLocal(const TBound &far_field_region,
00259 const TBound &local_field_region,
00260 double min_dist_sqd_regions,
00261 double max_dist_sqd_regions, double max_error,
00262 double *actual_error) const {
00263
00264
00265 double max_local_field_length =
00266 bounds_aux::MaxSideLengthOfBoundingBox(local_field_region);
00267
00268 double two_times_bandwidth = sqrt(kernel_.bandwidth_sq()) * 2;
00269 double r = max_local_field_length / two_times_bandwidth;
00270
00271 int dim = sea_.get_dimension();
00272 double r_raised_to_p_alpha = 1.0;
00273 double ret, ret2;
00274 int p_alpha = 0;
00275 double factorialvalue = 1.0;
00276 double first_factor, second_factor;
00277 double one_minus_r;
00278
00279
00280 if(r >= 1.0) {
00281 return -1;
00282 }
00283 one_minus_r = 1.0 - r;
00284 ret = 1.0 / pow(one_minus_r, dim);
00285
00286 do {
00287 factorialvalue *= (p_alpha + 1);
00288
00289 if(factorialvalue < 0.0 || p_alpha > sea_.get_max_order()) {
00290 return -1;
00291 }
00292
00293 r_raised_to_p_alpha *= r;
00294 first_factor = 1.0 - r_raised_to_p_alpha;
00295 second_factor = r_raised_to_p_alpha / sqrt(factorialvalue);
00296
00297 ret2 = ret * (pow((first_factor + second_factor), dim) -
00298 pow(first_factor, dim));
00299
00300 if(ret2 <= max_error) {
00301 break;
00302 }
00303
00304 p_alpha++;
00305
00306 } while(1);
00307
00308 *actual_error = ret2;
00309 return p_alpha;
00310 }
00311 };
00312
00315 class GaussianKernelAux {
00316
00317 public:
00318
00319 typedef GaussianKernel TKernel;
00320
00321 typedef SeriesExpansionAux TSeriesExpansionAux;
00322
00323 typedef FarFieldExpansion<GaussianKernelAux> TFarFieldExpansion;
00324
00325 typedef LocalExpansion<GaussianKernelAux> TLocalExpansion;
00326
00328 TKernel kernel_;
00329
00331 TSeriesExpansionAux sea_;
00332
00333 OT_DEF_BASIC(GaussianKernelAux) {
00334 OT_MY_OBJECT(kernel_);
00335 OT_MY_OBJECT(sea_);
00336 }
00337
00338 public:
00339
00340 void Init(double bandwidth, int max_order, int dim) {
00341 kernel_.Init(bandwidth);
00342 sea_.Init(max_order, dim);
00343 }
00344
00345 double BandwidthFactor(double bandwidth_sq) const {
00346 return sqrt(2 * bandwidth_sq);
00347 }
00348
00349 void AllocateDerivativeMap(int dim, int order,
00350 Matrix *derivative_map) const {
00351 derivative_map->Init(dim, order + 1);
00352 }
00353
00354 void ComputeDirectionalDerivatives(const Vector &x,
00355 Matrix *derivative_map, int order) const {
00356
00357 int dim = x.length();
00358
00359
00360 for(index_t d = 0; d < dim; d++) {
00361
00362 double coord_div_band = x[d];
00363 double d2 = 2 * coord_div_band;
00364 double facj = exp(-coord_div_band * coord_div_band);
00365
00366 derivative_map->set(d, 0, facj);
00367
00368 if(order > 0) {
00369
00370 derivative_map->set(d, 1, d2 * facj);
00371
00372 if(order > 1) {
00373 for(index_t k = 1; k < order; k++) {
00374 int k2 = k * 2;
00375 derivative_map->set(d, k + 1, d2 * derivative_map->get(d, k) -
00376 k2 * derivative_map->get(d, k - 1));
00377 }
00378 }
00379 }
00380 }
00381 }
00382
00383 double ComputePartialDerivative(const Matrix &derivative_map,
00384 const ArrayList<int> &mapping) const {
00385
00386 double partial_derivative = 1.0;
00387
00388 for(index_t d = 0; d < mapping.size(); d++) {
00389 partial_derivative *= derivative_map.get(d, mapping[d]);
00390 }
00391 return partial_derivative;
00392 }
00393
00394 template<typename TBound>
00395 int OrderForConvolvingFarField(const TBound &far_field_region,
00396 const Vector &far_field_region_centroid,
00397 const TBound &local_field_region,
00398 const Vector &local_field_region_centroid,
00399 double min_dist_sqd_regions,
00400 double max_dist_sqd_regions,
00401 double max_error,
00402 double *actual_error) const {
00403
00404 double squared_distance_between_two_centroids =
00405 la::DistanceSqEuclidean(far_field_region_centroid.length(),
00406 far_field_region_centroid.ptr(),
00407 local_field_region_centroid.ptr());
00408 double frontfactor =
00409 exp(-squared_distance_between_two_centroids /
00410 (4 * kernel_.bandwidth_sq()));
00411 int max_order = sea_.get_max_order();
00412
00413
00414
00415 double far_field_widest_width =
00416 bounds_aux::MaxSideLengthOfBoundingBox(far_field_region);
00417 double local_field_widest_width =
00418 bounds_aux::MaxSideLengthOfBoundingBox(local_field_region);
00419
00420 double two_bandwidth = 2 * sqrt(kernel_.bandwidth_sq());
00421 double r = (far_field_widest_width + local_field_widest_width) /
00422 two_bandwidth;
00423
00424 double r_raised_to_p_alpha = 1.0;
00425 double ret;
00426 int p_alpha = 0;
00427
00428 do {
00429
00430 if(p_alpha > max_order - 1) {
00431 return -1;
00432 }
00433
00434 r_raised_to_p_alpha *= r;
00435 frontfactor /= sqrt(p_alpha + 1);
00436
00437 ret = frontfactor * r_raised_to_p_alpha;
00438
00439 if(ret > max_error) {
00440 p_alpha++;
00441 }
00442 else {
00443 break;
00444 }
00445 } while(1);
00446
00447 *actual_error = ret;
00448 return p_alpha;
00449 }
00450
00451 template<typename TBound>
00452 int OrderForEvaluatingFarField(const TBound &far_field_region,
00453 const TBound &local_field_region,
00454 double min_dist_sqd_regions,
00455 double max_dist_sqd_regions,
00456 double max_error,
00457 double *actual_error) const {
00458
00459 double frontfactor =
00460 exp(-min_dist_sqd_regions / (4 * kernel_.bandwidth_sq()));
00461 int max_order = sea_.get_max_order();
00462
00463
00464
00465 double widest_width =
00466 bounds_aux::MaxSideLengthOfBoundingBox(far_field_region);
00467
00468 double two_bandwidth = 2 * sqrt(kernel_.bandwidth_sq());
00469 double r = widest_width / two_bandwidth;
00470
00471 double r_raised_to_p_alpha = 1.0;
00472 double ret;
00473 int p_alpha = 0;
00474
00475 do {
00476
00477 if(p_alpha > max_order - 1) {
00478 return -1;
00479 }
00480
00481 r_raised_to_p_alpha *= r;
00482 frontfactor /= sqrt(p_alpha + 1);
00483
00484 ret = frontfactor * r_raised_to_p_alpha;
00485
00486 if(ret > max_error) {
00487 p_alpha++;
00488 }
00489 else {
00490 break;
00491 }
00492 } while(1);
00493
00494 *actual_error = ret;
00495 return p_alpha;
00496 }
00497
00498 template<typename TBound>
00499 int OrderForConvertingFromFarFieldToLocal
00500 (const TBound &far_field_region, const TBound &local_field_region,
00501 double min_dist_sqd_regions, double max_dist_sqd_regions, double max_error,
00502 double *actual_error) const {
00503
00504
00505
00506 double max_ref_length =
00507 bounds_aux::MaxSideLengthOfBoundingBox(far_field_region);
00508 double max_query_length =
00509 bounds_aux::MaxSideLengthOfBoundingBox(local_field_region);
00510
00511 double two_times_bandwidth = sqrt(kernel_.bandwidth_sq()) * 2;
00512 double r_R = max_ref_length / two_times_bandwidth;
00513 double r_Q = max_query_length / two_times_bandwidth;
00514
00515 int p_alpha = -1;
00516 double r_Q_raised_to_p = 1.0;
00517 double r_R_raised_to_p = 1.0;
00518 double ret2;
00519 double frontfactor =
00520 exp(-min_dist_sqd_regions / (4.0 * kernel_.bandwidth_sq()));
00521 double first_factorial = 1.0;
00522 double second_factorial = 1.0;
00523 double r_Q_raised_to_p_cumulative = 1;
00524
00525 do {
00526 p_alpha++;
00527
00528 if(p_alpha > sea_.get_max_order() - 1) {
00529 return -1;
00530 }
00531
00532 first_factorial *= (p_alpha + 1);
00533 if(p_alpha > 0) {
00534 second_factorial *= sqrt(2 * p_alpha * (2 * p_alpha + 1));
00535 }
00536 r_Q_raised_to_p *= r_Q;
00537 r_R_raised_to_p *= r_R;
00538
00539 ret2 = frontfactor *
00540 (1.0 / first_factorial * r_R_raised_to_p * second_factorial *
00541 r_Q_raised_to_p_cumulative +
00542 1.0 / sqrt(first_factorial) * r_Q_raised_to_p);
00543
00544 r_Q_raised_to_p_cumulative += r_Q_raised_to_p /
00545 ((p_alpha > 0) ? (first_factorial / (p_alpha + 1)):first_factorial);
00546
00547 } while(ret2 >= max_error);
00548
00549 *actual_error = ret2;
00550 return p_alpha;
00551 }
00552
00553 template<typename TBound>
00554 int OrderForEvaluatingLocal
00555 (const TBound &far_field_region, const TBound &local_field_region,
00556 double min_dist_sqd_regions, double max_dist_sqd_regions, double max_error,
00557 double *actual_error) const {
00558
00559 double frontfactor =
00560 exp(-min_dist_sqd_regions / (4 * kernel_.bandwidth_sq()));
00561 int max_order = sea_.get_max_order();
00562
00563
00564
00565 double widest_width =
00566 bounds_aux::MaxSideLengthOfBoundingBox(local_field_region);
00567
00568 double two_bandwidth = 2 * sqrt(kernel_.bandwidth_sq());
00569 double r = widest_width / two_bandwidth;
00570
00571 double r_raised_to_p_alpha = 1.0;
00572 double ret;
00573 int p_alpha = 0;
00574
00575 do {
00576
00577 if(p_alpha > max_order - 1) {
00578 return -1;
00579 }
00580
00581 r_raised_to_p_alpha *= r;
00582 frontfactor /= sqrt(p_alpha + 1);
00583
00584 ret = frontfactor * r_raised_to_p_alpha;
00585
00586 if(ret > max_error) {
00587 p_alpha++;
00588 }
00589 else {
00590 break;
00591 }
00592 } while(1);
00593
00594 *actual_error = ret;
00595 return p_alpha;
00596 }
00597 };
00598
00602 class EpanKernelAux {
00603
00604 public:
00605
00606 typedef EpanKernel TKernel;
00607
00608 typedef SeriesExpansionAux TSeriesExpansionAux;
00609
00610 typedef FarFieldExpansion<EpanKernelAux> TFarFieldExpansion;
00611
00612 typedef LocalExpansion<EpanKernelAux> TLocalExpansion;
00613
00614 TKernel kernel_;
00615
00616 TSeriesExpansionAux sea_;
00617
00618 InversePowDistKernelAux squared_component_;
00619
00620 OT_DEF_BASIC(EpanKernelAux) {
00621 OT_MY_OBJECT(kernel_);
00622 OT_MY_OBJECT(sea_);
00623 OT_MY_OBJECT(squared_component_);
00624 }
00625
00626 public:
00627
00628 void Init(double bandwidth, int max_order, int dim) {
00629 kernel_.Init(bandwidth);
00630 sea_.Init(max_order, dim);
00631
00632
00633 squared_component_.Init(-2, max_order, dim);
00634 }
00635
00636 double BandwidthFactor(double bandwidth_sq) const {
00637 return sqrt(bandwidth_sq);
00638 }
00639
00640 void AllocateDerivativeMap(int dim, int order,
00641 Matrix *derivative_map) const {
00642 derivative_map->Init(sea_.get_total_num_coeffs(order), 1);
00643 }
00644
00645 void ComputeDirectionalDerivatives(const Vector &x,
00646 Matrix *derivative_map, int order) const {
00647
00648
00649
00650 squared_component_.ComputeDirectionalDerivatives(x, derivative_map, order);
00651
00652 la::Scale(derivative_map->n_rows(), -1, derivative_map->GetColumnPtr(0));
00653
00654 (derivative_map->GetColumnPtr(0))[0] += 1.0;
00655 }
00656
00657 double ComputePartialDerivative(const Matrix &derivative_map,
00658 const ArrayList<int> &mapping) const {
00659
00660 return derivative_map.get(sea_.ComputeMultiindexPosition(mapping), 0);
00661 }
00662
00663 template<typename TBound>
00664 int OrderForEvaluatingFarField
00665 (const TBound &far_field_region, const TBound &local_field_region,
00666 double min_dist_sqd_regions, double max_dist_sqd_regions,
00667 double max_error, double *actual_error) const {
00668
00669
00670
00671 if(max_dist_sqd_regions > kernel_.bandwidth_sq()) {
00672 return -1;
00673 }
00674
00675
00676
00677 double widest_width =
00678 bounds_aux::MaxSideLengthOfBoundingBox(far_field_region);
00679
00680
00681
00682 int dim;
00683 double farthest_distance_manhattan =
00684 bounds_aux::MaxL1Distance(far_field_region, local_field_region, &dim);
00685
00686
00687
00688 double two_bandwidth = 2 * sqrt(kernel_.bandwidth_sq());
00689 double r = widest_width / two_bandwidth;
00690 farthest_distance_manhattan /= sqrt(kernel_.bandwidth_sq());
00691
00692
00693 double error = 2 * dim * farthest_distance_manhattan * r;
00694 if(error < max_error) {
00695 *actual_error = error;
00696 return 0;
00697 }
00698
00699
00700 error = dim * r * r;
00701 if(error < max_error) {
00702 *actual_error = error;
00703 return 1;
00704 }
00705
00706
00707 *actual_error = 0;
00708 return 2;
00709 }
00710
00711 template<typename TBound>
00712 int OrderForConvertingFromFarFieldToLocal
00713 (const TBound &far_field_region, const TBound &local_field_region,
00714 double min_dist_sqd_regions, double max_dist_sqd_regions, double max_error,
00715 double *actual_error) const {
00716
00717
00718
00719 if(max_dist_sqd_regions > kernel_.bandwidth_sq() ||
00720 min_dist_sqd_regions == 0) {
00721 return -1;
00722 }
00723 else {
00724 *actual_error = 0;
00725 return 2;
00726 }
00727 }
00728
00729 template<typename TBound>
00730 int OrderForEvaluatingLocal
00731 (const TBound &far_field_region,
00732 const TBound &local_field_region,
00733 double min_dist_sqd_regions, double max_dist_sqd_regions,
00734 double max_error, double *actual_error) const {
00735
00736
00737
00738 if(max_dist_sqd_regions > kernel_.bandwidth_sq()) {
00739 return -1;
00740 }
00741
00742
00743
00744 double widest_width =
00745 bounds_aux::MaxSideLengthOfBoundingBox(local_field_region);
00746
00747
00748
00749 int dim;
00750 double farthest_distance_manhattan =
00751 bounds_aux::MaxL1Distance(far_field_region, local_field_region, &dim);
00752
00753
00754
00755 double two_bandwidth = 2 * sqrt(kernel_.bandwidth_sq());
00756 double r = widest_width / two_bandwidth;
00757 farthest_distance_manhattan /= sqrt(kernel_.bandwidth_sq());
00758
00759
00760 double error = 2 * dim * farthest_distance_manhattan * r;
00761 if(error < max_error) {
00762 *actual_error = error;
00763 return 0;
00764 }
00765
00766
00767 error = dim * math::Sqr(farthest_distance_manhattan);
00768 if(error < max_error) {
00769 *actual_error = error;
00770 return 1;
00771 }
00772
00773
00774 *actual_error = 0;
00775 return 2;
00776 }
00777 };
00778
00779 #endif