00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <climits>
00011
00012 #include "TError.h"
00013 #include "TMath.h"
00014
00015 #include "TKDEFGT.h"
00016 #include "TGL5D.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 TKDEFGT::TKDEFGT()
00028 : fDim(0),
00029 fP(0),
00030 fK(0),
00031 fSigma(1.),
00032 fPD(0),
00033 fModelValid(kFALSE)
00034 {
00035
00036 }
00037
00038 namespace {
00039
00040 UInt_t NChooseK(UInt_t n, UInt_t k);
00041
00042 }
00043
00044
00045 TKDEFGT::~TKDEFGT()
00046 {
00047
00048 }
00049
00050
00051 void TKDEFGT::BuildModel(const std::vector<Double_t> &sources, Double_t sigma,
00052 UInt_t dim, UInt_t p, UInt_t k)
00053 {
00054
00055 if (!sources.size()) {
00056 Warning("TKDEFGT::BuildModel", "Bad input - zero size vector");
00057 return;
00058 }
00059
00060 if (!dim) {
00061 Warning("TKDEFGT::BuildModel", "Number of dimensions is zero");
00062 return;
00063 }
00064
00065 if (!p) {
00066 Warning("TKDEFGT::BuildModel", "Order of truncation is zero, 8 will be used");
00067 p = 8;
00068 }
00069
00070 fDim = dim;
00071 fP = p;
00072 const UInt_t nP = UInt_t(sources.size()) / fDim;
00073 fK = !k ? UInt_t(TMath::Sqrt(Double_t(nP))) : k;
00074 fSigma = sigma;
00075 fPD = NChooseK(fP + fDim - 1, fDim);
00076
00077 fWeights.assign(nP, 1.);
00078 fXC.assign(fDim * fK, 0.);
00079 fA_K.assign(fPD * fK, 0.);
00080 fIndxc.assign(fK, 0);
00081 fIndx.assign(nP, 0);
00082 fXhead.assign(fK, 0);
00083 fXboxsz.assign(fK, 0);
00084 fDistC.assign(nP, 0.);
00085 fC_K.assign(fPD, 0.);
00086 fHeads.assign(fDim + 1, 0);
00087 fCinds.assign(fPD, 0);
00088 fDx.assign(fDim, 0.);
00089 fProds.assign(fPD, 0.);
00090
00091 Kcenter(sources);
00092 Compute_C_k();
00093 Compute_A_k(sources);
00094
00095 fModelValid = kTRUE;
00096 }
00097
00098
00099 void TKDEFGT::BuildModel(const TGL5DDataSet *sources, Double_t sigma, UInt_t p, UInt_t k)
00100 {
00101
00102
00103 if (!sources->SelectedSize()) {
00104 Warning("TKDEFGT::BuildModel", "Bad input - zero size vector");
00105 return;
00106 }
00107
00108 fDim = 3;
00109
00110 if (!p) {
00111 Warning("TKDEFGT::BuildModel", "Order of truncation is zero, 8 will be used");
00112 p = 8;
00113 }
00114
00115 fP = p;
00116 const UInt_t nP = sources->SelectedSize();
00117 fK = !k ? UInt_t(TMath::Sqrt(Double_t(nP))) : k;
00118 fSigma = sigma;
00119 fPD = NChooseK(fP + fDim - 1, fDim);
00120
00121 fWeights.assign(nP, 1.);
00122 fXC.assign(fDim * fK, 0.);
00123 fA_K.assign(fPD * fK, 0.);
00124 fIndxc.assign(fK, 0);
00125 fIndx.assign(nP, 0);
00126 fXhead.assign(fK, 0);
00127 fXboxsz.assign(fK, 0);
00128 fDistC.assign(nP, 0.);
00129 fC_K.assign(fPD, 0.);
00130 fHeads.assign(fDim + 1, 0);
00131 fCinds.assign(fPD, 0);
00132 fDx.assign(fDim, 0.);
00133 fProds.assign(fPD, 0.);
00134
00135 Kcenter(sources);
00136 Compute_C_k();
00137 Compute_A_k(sources);
00138
00139 fModelValid = kTRUE;
00140 }
00141
00142 void BuildModel();
00143
00144 namespace {
00145
00146 Double_t DDist(const Double_t *x , const Double_t *y , Int_t d);
00147 Double_t DDist(Double_t x1, Double_t y1, Double_t z1, Double_t x2, Double_t y2, Double_t z2);
00148
00149 UInt_t Idmax(const std::vector<Double_t> &x , UInt_t n);
00150
00151 }
00152
00153
00154 void TKDEFGT::Kcenter(const std::vector<double> &x)
00155 {
00156
00157
00158
00159 const UInt_t nP = UInt_t(x.size()) / fDim;
00160
00161 UInt_t *indxc = &fIndxc[0];
00162 UInt_t ind = 1;
00163 *indxc++ = ind;
00164
00165 const Double_t *x_j = &x[0];
00166 const Double_t *x_ind = &x[0] + ind * fDim;
00167
00168 for (UInt_t j = 0; j < nP; x_j += fDim, ++j) {
00169 fDistC[j] = (j == ind) ? 0. : DDist(x_j , x_ind , fDim);
00170 fIndx[j] = 0;
00171 }
00172
00173 for (UInt_t i = 1 ; i < fK; ++i) {
00174 ind = Idmax(fDistC, nP);
00175 *indxc++ = ind;
00176 x_j = &x[0];
00177 x_ind = &x[0] + ind * fDim;
00178 for (UInt_t j = 0; j < nP; x_j += fDim, ++j) {
00179 const Double_t temp = (j==ind) ? 0.0 : DDist(x_j, x_ind, fDim);
00180 if (temp < fDistC[j]) {
00181 fDistC[j] = temp;
00182 fIndx[j] = i;
00183 }
00184 }
00185 }
00186
00187 for (UInt_t i = 0, nd = 0 ; i < nP; i++, nd += fDim) {
00188 fXboxsz[fIndx[i]]++;
00189 Int_t ibase = fIndx[i] * fDim;
00190 for (UInt_t j = 0 ; j < fDim; ++j)
00191 fXC[j + ibase] += x[j + nd];
00192 }
00193
00194 for (UInt_t i = 0, ibase = 0; i < fK ; ++i, ibase += fDim) {
00195 const Double_t temp = 1. / fXboxsz[i];
00196 for (UInt_t j = 0; j < fDim; ++j)
00197 fXC[j + ibase] *= temp;
00198 }
00199 }
00200
00201
00202 void TKDEFGT::Kcenter(const TGL5DDataSet *sources)
00203 {
00204
00205
00206 const UInt_t nP = sources->SelectedSize();
00207
00208 UInt_t *indxc = &fIndxc[0];
00209 *indxc++ = 1;
00210
00211 {
00212
00213 const Double_t x_ind = sources->V1(1);
00214 const Double_t y_ind = sources->V2(1);
00215 const Double_t z_ind = sources->V3(1);
00216
00217 for (UInt_t j = 0; j < nP; ++j) {
00218 const Double_t x_j = sources->V1(j);
00219 const Double_t y_j = sources->V2(j);
00220 const Double_t z_j = sources->V3(j);
00221 fDistC[j] = (j == 1) ? 0. : DDist(x_j, y_j, z_j, x_ind, y_ind, z_ind);
00222 fIndx[j] = 0;
00223 }
00224
00225 }
00226
00227 for (UInt_t i = 1 ; i < fK; ++i) {
00228 const UInt_t ind = Idmax(fDistC, nP);
00229 const Double_t x_ind = sources->V1(ind);
00230 const Double_t y_ind = sources->V2(ind);
00231 const Double_t z_ind = sources->V3(ind);
00232
00233 *indxc++ = ind;
00234 for (UInt_t j = 0; j < nP; ++j) {
00235 const Double_t x_j = sources->V1(j);
00236 const Double_t y_j = sources->V2(j);
00237 const Double_t z_j = sources->V3(j);
00238
00239 const Double_t temp = (j==ind) ? 0.0 : DDist(x_j, y_j, z_j, x_ind, y_ind, z_ind);
00240 if (temp < fDistC[j]) {
00241 fDistC[j] = temp;
00242 fIndx[j] = i;
00243 }
00244 }
00245 }
00246
00247 for (UInt_t i = 0, nd = 0 ; i < nP; i++, nd += fDim) {
00248 fXboxsz[fIndx[i]]++;
00249 UInt_t ibase = fIndx[i] * fDim;
00250 fXC[ibase] += sources->V1(i);
00251 fXC[ibase + 1] += sources->V2(i);
00252 fXC[ibase + 2] += sources->V3(i);
00253 }
00254
00255 for (UInt_t i = 0, ibase = 0; i < fK ; ++i, ibase += fDim) {
00256 const Double_t temp = 1. / fXboxsz[i];
00257 for (UInt_t j = 0; j < fDim; ++j)
00258 fXC[j + ibase] *= temp;
00259 }
00260 }
00261
00262
00263 void TKDEFGT::Compute_C_k()
00264 {
00265
00266 fHeads[fDim] = UINT_MAX;
00267 fCinds[0] = 0;
00268 fC_K[0] = 1.0;
00269
00270 for (UInt_t k = 1, t = 1, tail = 1; k < fP; ++k, tail = t) {
00271 for (UInt_t i = 0; i < fDim; ++i) {
00272 const UInt_t head = fHeads[i];
00273 fHeads[i] = t;
00274 for (UInt_t j = head; j < tail; ++j, ++t) {
00275 fCinds[t] = (j < fHeads[i + 1]) ? fCinds[j] + 1 : 1;
00276 fC_K[t] = 2.0 * fC_K[j];
00277 fC_K[t] /= fCinds[t];
00278 }
00279 }
00280 }
00281 }
00282
00283
00284 void TKDEFGT::Compute_A_k(const std::vector<Double_t> &x)
00285 {
00286
00287 const Double_t ctesigma = 1. / fSigma;
00288 const UInt_t nP = UInt_t(x.size()) / fDim;
00289
00290 for (UInt_t n = 0; n < nP; n++) {
00291 UInt_t nbase = n * fDim;
00292 UInt_t ix2c = fIndx[n];
00293 UInt_t ix2cbase = ix2c * fDim;
00294 UInt_t ind = ix2c * fPD;
00295 Double_t temp = fWeights[n];
00296 Double_t sum = 0.0;
00297
00298 for (UInt_t i = 0; i < fDim; ++i) {
00299 fDx[i] = (x[i + nbase] - fXC[i + ix2cbase]) * ctesigma;
00300 sum += fDx[i] * fDx[i];
00301 fHeads[i] = 0;
00302 }
00303
00304 fProds[0] = TMath::Exp(-sum);
00305
00306 for (UInt_t k = 1, t = 1, tail = 1; k < fP; ++k, tail = t) {
00307 for (UInt_t i = 0; i < fDim; ++i) {
00308 const UInt_t head = fHeads[i];
00309 fHeads[i] = t;
00310 const Double_t temp1 = fDx[i];
00311 for (UInt_t j = head; j < tail; ++j, ++t)
00312 fProds[t] = temp1 * fProds[j];
00313 }
00314 }
00315
00316 for (UInt_t i = 0 ; i < fPD ; i++)
00317 fA_K[i + ind] += temp * fProds[i];
00318 }
00319
00320 for (UInt_t k = 0; k < fK; ++k) {
00321 const UInt_t ind = k * fPD;
00322 for (UInt_t i = 0; i < fPD; ++i)
00323 fA_K[i + ind] *= fC_K[i];
00324 }
00325 }
00326
00327
00328 void TKDEFGT::Compute_A_k(const TGL5DDataSet *sources)
00329 {
00330
00331 const Double_t ctesigma = 1. / fSigma;
00332 const UInt_t nP = sources->SelectedSize();
00333
00334 for (UInt_t n = 0; n < nP; n++) {
00335 UInt_t ix2c = fIndx[n];
00336 UInt_t ix2cbase = ix2c * 3;
00337 UInt_t ind = ix2c * fPD;
00338 Double_t temp = fWeights[n];
00339 Double_t sum = 0.0;
00340
00341 fDx[0] = (sources->V1(n) - fXC[ix2cbase]) * ctesigma;
00342 fDx[1] = (sources->V2(n) - fXC[ix2cbase + 1]) * ctesigma;
00343 fDx[2] = (sources->V3(n) - fXC[ix2cbase + 2]) * ctesigma;
00344
00345 sum += (fDx[0] * fDx[0] + fDx[1] * fDx[1] + fDx[2] * fDx[2]);
00346 fHeads[0] = fHeads[1] = fHeads[2] = 0;
00347
00348 fProds[0] = TMath::Exp(-sum);
00349
00350 for (UInt_t k = 1, t = 1, tail = 1; k < fP; ++k, tail = t) {
00351 for (UInt_t i = 0; i < 3; ++i) {
00352 const UInt_t head = fHeads[i];
00353 fHeads[i] = t;
00354 const Double_t temp1 = fDx[i];
00355 for (UInt_t j = head; j < tail; ++j, ++t)
00356 fProds[t] = temp1 * fProds[j];
00357 }
00358 }
00359
00360 for (UInt_t i = 0 ; i < fPD ; i++)
00361 fA_K[i + ind] += temp * fProds[i];
00362 }
00363
00364 for (UInt_t k = 0; k < fK; ++k) {
00365 const Int_t ind = k * fPD;
00366 for (UInt_t i = 0; i < fPD; ++i)
00367 fA_K[i + ind] *= fC_K[i];
00368 }
00369 }
00370
00371 namespace {
00372
00373 UInt_t InvNChooseK(UInt_t d, UInt_t cnk);
00374
00375 }
00376
00377
00378 void TKDEFGT::Predict(const std::vector<Double_t> &ts, std::vector<Double_t> &v, Double_t eval)const
00379 {
00380
00381
00382 if (!fModelValid) {
00383 Error("TKDEFGT::Predict", "Call BuildModel first!");
00384 return;
00385 }
00386
00387 if (!ts.size()) {
00388 Warning("TKDEFGT::Predict", "Empty targets vector.");
00389 return;
00390 }
00391
00392 v.assign(ts.size() / fDim, 0.);
00393
00394 fHeads.assign(fDim + 1, 0);
00395 fDx.assign(fDim, 0.);
00396 fProds.assign(fPD, 0.);
00397
00398 const Double_t ctesigma = 1. / fSigma;
00399 const UInt_t p = InvNChooseK(fDim , fPD);
00400 const UInt_t nP = UInt_t(ts.size()) / fDim;
00401
00402 for (UInt_t m = 0; m < nP; ++m) {
00403 Double_t temp = 0.;
00404 const UInt_t mbase = m * fDim;
00405
00406 for (UInt_t kn = 0 ; kn < fK ; ++kn) {
00407 const UInt_t xbase = kn * fDim;
00408 const UInt_t ind = kn * fPD;
00409 Double_t sum2 = 0.0;
00410 for (UInt_t i = 0; i < fDim ; ++i) {
00411 fDx[i] = (ts[i + mbase] - fXC[i + xbase]) * ctesigma;
00412 sum2 += fDx[i] * fDx[i];
00413 fHeads[i] = 0;
00414 }
00415
00416 if (sum2 > eval) continue;
00417
00418 fProds[0] = TMath::Exp(-sum2);
00419
00420 for (UInt_t k = 1, t = 1, tail = 1; k < p; ++k, tail = t) {
00421 for (UInt_t i = 0; i < fDim; ++i) {
00422 UInt_t head = fHeads[i];
00423 fHeads[i] = t;
00424 const Double_t temp1 = fDx[i];
00425 for (UInt_t j = head; j < tail; ++j, ++t)
00426 fProds[t] = temp1 * fProds[j];
00427 }
00428 }
00429
00430 for (UInt_t i = 0 ; i < fPD ; ++i)
00431 temp += fA_K[i + ind] * fProds[i];
00432 }
00433
00434 v[m] = temp;
00435 }
00436
00437 Double_t dMin = v[0], dMax = dMin;
00438 for (UInt_t i = 1; i < nP; ++i) {
00439 dMin = TMath::Min(dMin, v[i]);
00440 dMax = TMath::Max(dMax, v[i]);
00441 }
00442
00443 const Double_t dRange = dMax - dMin;
00444 for (UInt_t i = 0; i < nP; ++i)
00445 v[i] = (v[i] - dMin) / dRange;
00446
00447 dMin = v[0], dMax = dMin;
00448 for (UInt_t i = 1; i < nP; ++i) {
00449 dMin = TMath::Min(dMin, v[i]);
00450 dMax = TMath::Max(dMax, v[i]);
00451 }
00452 }
00453
00454 namespace {
00455
00456
00457 UInt_t NChooseK(UInt_t n, UInt_t k)
00458 {
00459
00460 UInt_t n_k = n - k;
00461 if (k < n_k) {
00462 k = n_k;
00463 n_k = n - k;
00464 }
00465 UInt_t nchsk = 1;
00466 for (UInt_t i = 1; i <= n_k; ++i) {
00467 nchsk *= ++k;
00468 nchsk /= i;
00469 }
00470
00471 return nchsk;
00472 }
00473
00474
00475 Double_t DDist(Double_t x1, Double_t y1, Double_t z1, Double_t x2, Double_t y2, Double_t z2)
00476 {
00477 return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
00478 }
00479
00480
00481 Double_t DDist(const Double_t *x , const Double_t *y , Int_t d)
00482 {
00483 Double_t t = 0., s = 0.;
00484
00485 for (Int_t i = 0 ; i < d ; i++) {
00486 t = (x[i] - y[i]);
00487 s += (t * t);
00488 }
00489
00490 return s;
00491 }
00492
00493
00494 UInt_t Idmax(const std::vector<Double_t> &x , UInt_t n)
00495 {
00496 UInt_t k = 0;
00497 Double_t t = -1.0;
00498 for (UInt_t i = 0; i < n; ++i) {
00499 if (t < x[i]) {
00500 t = x[i];
00501 k = i;
00502 }
00503 }
00504
00505 return k;
00506 }
00507
00508
00509 UInt_t InvNChooseK(UInt_t d, UInt_t cnk)
00510 {
00511 UInt_t cted = 1;
00512 for (UInt_t i = 2 ; i <= d ; ++i)
00513 cted *= i;
00514
00515 const UInt_t cte = cnk * cted;
00516 UInt_t p = 2, ctep = 2;
00517
00518 for (UInt_t i = p + 1; i < p + d; ++i)
00519 ctep *= i;
00520
00521 while (ctep != cte) {
00522 ctep = ((p + d) * ctep) / p;
00523 ++p;
00524 }
00525
00526 return p;
00527 }
00528
00529 }