00001 #ifndef INDII_ML_AUX_KDE_HPP
00002 #define INDII_ML_AUX_KDE_HPP
00003
00004 #include "PartitionTree.hpp"
00005
00006
00007
00008
00009
00010
00011
00012
00013 namespace indii {
00014 namespace ml {
00015 namespace aux {
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 double hopt(const unsigned int N, const unsigned int P);
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 template <class NT, class KT, class PT>
00061 vector dualTreeDensity(PT& queryTree, PT& targetTree,
00062 const vector& w, const NT& N, const KT& K, const bool normalise = true);
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 template <class NT, class KT, class PT>
00087 vector distributedDualTreeDensity(PT& queryTree,
00088 PT& targetTree, const vector& w, const NT& N, const KT& K,
00089 const bool normalise = true);
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 template <class NT, class KT, class PT>
00108 vector selfTreeDensity(PT& tree, const vector& w, const NT& N,
00109 const KT& K, const bool normalise = true);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 template <class NT, class KT, class PT>
00130 vector distributedSelfTreeDensity(PT& tree, const vector& w,
00131 const NT& N, const KT& K, const bool normalise = true);
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 template <class NT, class KT, class PT>
00157 matrix dualTreeDensity(PT& queryTree, PT& targetTree,
00158 const matrix& ws, const NT& N, const KT& K, const bool normalise = true);
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 template <class NT, class KT, class PT>
00185 matrix distributedDualTreeDensity(PT& queryTree,
00186 PT& targetTree, const matrix& ws, const NT& N, const KT& K,
00187 const bool normalise = true);
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 template <class NT, class KT, class PT>
00210 matrix selfTreeDensity(PT& tree, const matrix& ws, const NT& N,
00211 const KT& K, const bool normalise = true);
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 template <class NT, class KT, class PT>
00234 matrix distributedSelfTreeDensity(PT& tree, const matrix& ws,
00235 const NT& N, const KT& K, const bool normalise = true);
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 template <class NT, class KT, class PT>
00264 void crossTreeDensity(PT& tree1, PT& tree2,
00265 const matrix& ws1, const matrix& ws2, const NT& N, const KT& K,
00266 matrix& result1, matrix& result2, const bool clear = true,
00267 const bool normalise = true);
00268
00269 }
00270 }
00271 }
00272
00273 #include "DiracMixturePdf.hpp"
00274 #include "KDTree.hpp"
00275 #include "vector.hpp"
00276 #include "matrix.hpp"
00277
00278 #include <stack>
00279
00280 inline double indii::ml::aux::hopt(const unsigned int N,
00281 const unsigned int P) {
00282 return pow(4.0/((N+2)*P), 1.0/(N+4.0));
00283 }
00284
00285 template <class NT, class KT, class PT>
00286 indii::ml::aux::vector indii::ml::aux::dualTreeDensity(
00287 PT& queryTree, PT& targetTree, const vector& w,
00288 const NT& N, const KT& K, const bool normalise) {
00289 aux::matrix ws(1,w.size());
00290 row(ws,0) = w;
00291 return row(dualTreeDensity(queryTree, targetTree, ws, N, K, normalise), 0);
00292 }
00293
00294 template <class NT, class KT, class PT>
00295 indii::ml::aux::vector indii::ml::aux::distributedDualTreeDensity(
00296 PT& queryTree, PT& targetTree, const vector& w,
00297 const NT& N, const KT& K, const bool normalise) {
00298 aux::matrix ws(1,w.size());
00299 row(ws,0) = w;
00300 return row(distributedDualTreeDensity(queryTree, targetTree, ws, N, K,
00301 normalise), 0);
00302 }
00303
00304 template <class NT, class KT, class PT>
00305 indii::ml::aux::vector indii::ml::aux::selfTreeDensity(
00306 PT& tree, const vector& w, const NT& N, const KT& K,
00307 const bool normalise) {
00308 aux::matrix ws(1,w.size());
00309 row(ws,0) = w;
00310 return row(selfTreeDensity(tree, ws, N, K, normalise), 0);
00311 }
00312
00313 template <class NT, class KT, class PT>
00314 indii::ml::aux::vector indii::ml::aux::distributedSelfTreeDensity(
00315 PT& tree, const vector& w, const NT& N, const KT& K,
00316 const bool normalise) {
00317 aux::matrix ws(1,w.size());
00318 row(ws,0) = w;
00319 return row(distributedSelfTreeDensity(tree, ws, N, K, normalise), 0);
00320 }
00321
00322 template <class NT, class KT, class PT>
00323 indii::ml::aux::matrix indii::ml::aux::dualTreeDensity(
00324 PT& queryTree, PT& targetTree, const matrix& ws,
00325 const NT& N, const KT& K, const bool normalise) {
00326
00327 assert (ws.size2() == targetTree.getData()->getSize());
00328 assert (queryTree.getData()->getDimensions() ==
00329 targetTree.getData()->getDimensions());
00330
00331 DiracMixturePdf& q = *queryTree.getData();
00332 DiracMixturePdf& p = *targetTree.getData();
00333 PartitionTreeNode* queryRoot = queryTree.getRoot();
00334 PartitionTreeNode* targetRoot = targetTree.getRoot();
00335
00336 matrix result(ws.size1(), q.getSize());
00337 result.clear();
00338
00339 if (queryRoot != NULL && targetRoot != NULL) {
00340 std::stack<PartitionTreeNode*> queryNodes, targetNodes;
00341
00342 vector x(p.getDimensions());
00343 unsigned int i, j;
00344 double w, d;
00345
00346 queryNodes.push(queryRoot);
00347 targetNodes.push(targetRoot);
00348
00349 while (!queryNodes.empty()) {
00350 PartitionTreeNode& queryNode = *queryNodes.top();
00351 queryNodes.pop();
00352 PartitionTreeNode& targetNode = *targetNodes.top();
00353 targetNodes.pop();
00354
00355 if (queryNode.isLeaf() && targetNode.isLeaf()) {
00356 i = queryNode.getIndex();
00357 j = targetNode.getIndex();
00358 noalias(x) = q.get(i) - p.get(j);
00359 d = K(N(x));
00360 noalias(column(result,i)) += d * column(ws,j);
00361 } else if (queryNode.isLeaf() && targetNode.isPrune()) {
00362 i = queryNode.getIndex();
00363 const std::vector<unsigned int>& js = targetNode.getIndices();
00364 for (j = 0; j < js.size(); j++) {
00365 noalias(x) = q.get(i) - p.get(js[j]);
00366 d = K(N(x));
00367 noalias(column(result,i)) += d * column(ws,js[j]);
00368 }
00369 } else if (queryNode.isPrune() && targetNode.isLeaf()) {
00370 const std::vector<unsigned int>& is = queryNode.getIndices();
00371 j = targetNode.getIndex();
00372 for (i = 0; i < is.size(); i++) {
00373 noalias(x) = q.get(is[i]) - p.get(j);
00374 d = K(N(x));
00375 noalias(column(result,is[i])) += d * column(ws,j);
00376 }
00377 } else if (queryNode.isPrune() && targetNode.isPrune()) {
00378 const std::vector<unsigned int>& is = queryNode.getIndices();
00379 const std::vector<unsigned int>& js = targetNode.getIndices();
00380 for (i = 0; i < is.size(); i++) {
00381 for (j = 0; j < js.size(); j++) {
00382 noalias(x) = q.get(is[i]) - p.get(js[j]);
00383 d = K(N(x));
00384 noalias(column(result,is[i])) += d * column(ws,js[j]);
00385 }
00386 }
00387 } else {
00388
00389 targetNode.difference(queryNode, x);
00390 if (K(N(x)) > 0.0) {
00391 if (queryNode.isInternal()) {
00392 if (targetNode.isInternal()) {
00393
00394 queryNodes.push(queryNode.getLeft());
00395 targetNodes.push(targetNode.getLeft());
00396
00397 queryNodes.push(queryNode.getLeft());
00398 targetNodes.push(targetNode.getRight());
00399
00400 queryNodes.push(queryNode.getRight());
00401 targetNodes.push(targetNode.getLeft());
00402
00403 queryNodes.push(queryNode.getRight());
00404 targetNodes.push(targetNode.getRight());
00405 } else {
00406
00407 queryNodes.push(queryNode.getLeft());
00408 targetNodes.push(&targetNode);
00409
00410 queryNodes.push(queryNode.getRight());
00411 targetNodes.push(&targetNode);
00412 }
00413 } else {
00414
00415 queryNodes.push(&queryNode);
00416 targetNodes.push(targetNode.getLeft());
00417
00418 queryNodes.push(&queryNode);
00419 targetNodes.push(targetNode.getRight());
00420 }
00421 }
00422 }
00423 }
00424
00425 if (normalise) {
00426 result /= p.getTotalWeight();
00427 }
00428 }
00429
00430 return result;
00431 }
00432
00433 template <class NT, class KT, class PT>
00434 indii::ml::aux::matrix indii::ml::aux::distributedDualTreeDensity(
00435 PT& queryTree, PT& targetTree, const matrix& ws,
00436 const NT& N, const KT& K, const bool normalise) {
00437 boost::mpi::communicator world;
00438 const unsigned int size = world.size();
00439 unsigned int i;
00440
00441 matrix result(dualTreeDensity(queryTree, targetTree, ws, N, K, false));
00442 rotate(*queryTree.getData());
00443 rotate(queryTree);
00444 rotate(result);
00445
00446 for (i = 1; i < size; i++) {
00447 noalias(result) += dualTreeDensity(queryTree, targetTree, ws, N, K,
00448 false);
00449 rotate(*queryTree.getData());
00450 rotate(queryTree);
00451 rotate(result);
00452 }
00453
00454 if (normalise) {
00455 result /= targetTree.getData()->getDistributedTotalWeight();
00456 }
00457
00458 return result;
00459 }
00460
00461 template <class NT, class KT, class PT>
00462 indii::ml::aux::matrix indii::ml::aux::selfTreeDensity(PT& tree,
00463 const matrix& ws, const NT& N, const KT& K, const bool normalise) {
00464
00465 assert (ws.size2() == tree.getData()->getSize());
00466
00467 DiracMixturePdf& p = *tree.getData();
00468 PartitionTreeNode* root = tree.getRoot();
00469
00470 matrix result(ws.size1(), p.getSize());
00471 result.clear();
00472
00473 if (root != NULL) {
00474 std::stack<PartitionTreeNode*> queryNodes, targetNodes;
00475 std::stack<bool> doCrosses;
00476
00477 vector x(p.getDimensions());
00478 unsigned int i, j;
00479 double w, d;
00480 bool doCross;
00481
00482 queryNodes.push(root);
00483 targetNodes.push(root);
00484 doCrosses.push(false);
00485
00486 while (!queryNodes.empty()) {
00487 PartitionTreeNode& queryNode = *queryNodes.top();
00488 queryNodes.pop();
00489 PartitionTreeNode& targetNode = *targetNodes.top();
00490 targetNodes.pop();
00491 doCross = doCrosses.top();
00492 doCrosses.pop();
00493
00494 if (queryNode.isLeaf() && targetNode.isLeaf()) {
00495 i = queryNode.getIndex();
00496 j = targetNode.getIndex();
00497 noalias(x) = p.get(i) - p.get(j);
00498 d = K(N(x));
00499 if (doCross) {
00500 noalias(column(result,j)) += d * column(ws,i);
00501 }
00502 noalias(column(result,i)) += d * column(ws,j);
00503 } else if (queryNode.isLeaf() && targetNode.isPrune()) {
00504 i = queryNode.getIndex();
00505 const std::vector<unsigned int>& js = targetNode.getIndices();
00506 for (j = 0; j < js.size(); j++) {
00507 noalias(x) = p.get(i) - p.get(js[j]);
00508 d = K(N(x));
00509 if (doCross) {
00510 noalias(column(result,js[j])) += d * column(ws,i);
00511 }
00512 noalias(column(result,i)) += d * column(ws,js[j]);
00513 }
00514 } else if (queryNode.isPrune() && targetNode.isLeaf()) {
00515 const std::vector<unsigned int>& is = queryNode.getIndices();
00516 j = targetNode.getIndex();
00517 for (i = 0; i < is.size(); i++) {
00518 noalias(x) = p.get(is[i]) - p.get(j);
00519 d = K(N(x));
00520 if (doCross) {
00521 noalias(column(result,j)) += d * column(ws,is[i]);
00522 }
00523 noalias(column(result,is[i])) += d * column(ws,j);
00524 }
00525 } else if (queryNode.isPrune() && targetNode.isPrune()) {
00526 const std::vector<unsigned int>& is = queryNode.getIndices();
00527 const std::vector<unsigned int>& js = targetNode.getIndices();
00528 for (i = 0; i < is.size(); i++) {
00529 for (j = 0; j < js.size(); j++) {
00530 noalias(x) = p.get(is[i]) - p.get(js[j]);
00531 d = K(N(x));
00532 if (doCross) {
00533 noalias(column(result,js[j])) += d * column(ws,is[i]);
00534 }
00535 noalias(column(result,is[i])) += d * column(ws,js[j]);
00536 }
00537 }
00538 } else {
00539
00540 targetNode.difference(queryNode, x);
00541 if (K(N(x)) > 0.0) {
00542 if (queryNode.isInternal()) {
00543 if (targetNode.isInternal()) {
00544
00545 queryNodes.push(queryNode.getLeft());
00546 targetNodes.push(targetNode.getLeft());
00547 doCrosses.push(doCross);
00548
00549 queryNodes.push(queryNode.getLeft());
00550 targetNodes.push(targetNode.getRight());
00551 if (&queryNode == &targetNode) {
00552
00553 doCrosses.push(true);
00554 } else {
00555
00556 doCrosses.push(doCross);
00557
00558 queryNodes.push(queryNode.getRight());
00559 targetNodes.push(targetNode.getLeft());
00560 doCrosses.push(doCross);
00561 }
00562
00563 queryNodes.push(queryNode.getRight());
00564 targetNodes.push(targetNode.getRight());
00565 doCrosses.push(doCross);
00566 } else {
00567
00568 queryNodes.push(queryNode.getLeft());
00569 targetNodes.push(&targetNode);
00570 doCrosses.push(doCross);
00571
00572 queryNodes.push(queryNode.getRight());
00573 targetNodes.push(&targetNode);
00574 doCrosses.push(doCross);
00575 }
00576 } else {
00577
00578 queryNodes.push(&queryNode);
00579 targetNodes.push(targetNode.getLeft());
00580 doCrosses.push(doCross);
00581
00582 queryNodes.push(&queryNode);
00583 targetNodes.push(targetNode.getRight());
00584 doCrosses.push(doCross);
00585 }
00586 }
00587 }
00588 }
00589
00590 if (normalise) {
00591 result /= p.getTotalWeight();
00592 }
00593 }
00594
00595 return result;
00596 }
00597
00598 template <class NT, class KT, class PT>
00599 indii::ml::aux::matrix indii::ml::aux::distributedSelfTreeDensity(
00600 PT& tree, const matrix& ws, const NT& N, const KT& K,
00601 const bool normalise) {
00602 boost::mpi::communicator world;
00603 const unsigned int size = world.size();
00604
00605 matrix result(selfTreeDensity(tree, ws, N, K, false));
00606
00607 if (size > 1) {
00608
00609 unsigned int crosses = (size - 1) / 2;
00610 bool leftover = (size - 1) % 2 > 0;
00611 unsigned int i;
00612
00613 matrix ws2(ws);
00614 matrix result2(result.size1(), result.size2());
00615 result2.clear();
00616
00617 PT* tree2 = dynamic_cast<PT*>(tree.clone());
00618 DiracMixturePdf q(*tree.getData());
00619 tree2->setData(&q);
00620
00621 for (i = 0; i < crosses; i++) {
00622 rotate(*tree2->getData());
00623 rotate(*tree2);
00624 rotate(result2);
00625 rotate(ws2);
00626 crossTreeDensity(tree, *tree2, ws, ws2, N, K, result, result2,
00627 false, false);
00628 }
00629
00630 if (leftover) {
00631 rotate(*tree2->getData());
00632 rotate(*tree2);
00633 rotate(ws2);
00634 noalias(result) += dualTreeDensity(tree, *tree2, ws2, N, K, false);
00635 }
00636
00637
00638 rotate(result2, size - i);
00639 noalias(result) += result2;
00640
00641 delete tree2;
00642 }
00643
00644 if (normalise) {
00645 result /= tree.getData()->getDistributedTotalWeight();
00646 }
00647
00648 return result;
00649 }
00650
00651 template <class NT, class KT, class PT>
00652 void indii::ml::aux::crossTreeDensity(
00653 PT& tree1, PT& tree2, const matrix& ws1,
00654 const matrix& ws2, const NT& N, const KT& K, matrix& result1,
00655 matrix& result2, const bool clear, const bool normalise) {
00656
00657 assert (ws1.size2() == tree1.getData()->getSize());
00658 assert (ws2.size2() == tree2.getData()->getSize());
00659 assert (result1.size2() == tree1.getData()->getSize());
00660 assert (result2.size2() == tree2.getData()->getSize());
00661 assert (result1.size1() == ws1.size1());
00662 assert (result2.size1() == ws2.size1());
00663 assert (tree1.getData()->getDimensions() ==
00664 tree2.getData()->getDimensions());
00665
00666 DiracMixturePdf& p1 = *tree1.getData();
00667 DiracMixturePdf& p2 = *tree2.getData();
00668 PartitionTreeNode* root1 = tree1.getRoot();
00669 PartitionTreeNode* root2 = tree2.getRoot();
00670
00671 if (clear) {
00672 result1.clear();
00673 result2.clear();
00674 }
00675
00676 if (root1 != NULL && root2 != NULL) {
00677 std::stack<PartitionTreeNode*> nodes1, nodes2;
00678
00679 vector x(p1.getDimensions());
00680 unsigned int i, j;
00681 double w, d;
00682
00683 nodes1.push(root1);
00684 nodes2.push(root2);
00685
00686 while (!nodes1.empty()) {
00687 PartitionTreeNode& node1 = *nodes1.top();
00688 nodes1.pop();
00689 PartitionTreeNode& node2 = *nodes2.top();
00690 nodes2.pop();
00691
00692 if (node1.isLeaf() && node2.isLeaf()) {
00693 i = node1.getIndex();
00694 j = node2.getIndex();
00695 noalias(x) = p1.get(i) - p2.get(j);
00696 d = K(N(x));
00697 noalias(column(result1,i)) += d * column(ws2,j);
00698 noalias(column(result2,j)) += d * column(ws1,i);
00699 } else if (node1.isLeaf() && node2.isPrune()) {
00700 i = node1.getIndex();
00701 const std::vector<unsigned int>& js = node2.getIndices();
00702 for (j = 0; j < js.size(); j++) {
00703 noalias(x) = p1.get(i) - p2.get(js[j]);
00704 d = K(N(x));
00705 noalias(column(result1,i)) += d * column(ws2,js[j]);
00706 noalias(column(result2,js[j])) += d * column(ws1,i);
00707 }
00708 } else if (node1.isPrune() && node2.isLeaf()) {
00709 const std::vector<unsigned int>& is = node1.getIndices();
00710 j = node2.getIndex();
00711 for (i = 0; i < is.size(); i++) {
00712 noalias(x) = p1.get(is[i]) - p2.get(j);
00713 d = K(N(x));
00714 noalias(column(result1,is[i])) += d * column(ws2,j);
00715 noalias(column(result2,j)) += d * column(ws1,is[i]);
00716 }
00717 } else if (node1.isPrune() && node2.isPrune()) {
00718 const std::vector<unsigned int>& is = node1.getIndices();
00719 const std::vector<unsigned int>& js = node2.getIndices();
00720 for (i = 0; i < is.size(); i++) {
00721 for (j = 0; j < js.size(); j++) {
00722 noalias(x) = p1.get(is[i]) - p2.get(js[j]);
00723 d = K(N(x));
00724 noalias(column(result1,is[i])) += d * column(ws2,js[j]);
00725 noalias(column(result2,js[j])) += d * column(ws1,is[i]);
00726 }
00727 }
00728 } else {
00729
00730 node2.difference(node1, x);
00731 if (K(N(x)) > 0.0) {
00732 if (node1.isInternal()) {
00733 if (node2.isInternal()) {
00734
00735 nodes1.push(node1.getLeft());
00736 nodes2.push(node2.getLeft());
00737
00738 nodes1.push(node1.getLeft());
00739 nodes2.push(node2.getRight());
00740
00741 nodes1.push(node1.getRight());
00742 nodes2.push(node2.getLeft());
00743
00744 nodes1.push(node1.getRight());
00745 nodes2.push(node2.getRight());
00746 } else {
00747
00748 nodes1.push(node1.getLeft());
00749 nodes2.push(&node2);
00750
00751 nodes1.push(node1.getRight());
00752 nodes2.push(&node2);
00753 }
00754 } else {
00755
00756 nodes1.push(&node1);
00757 nodes2.push(node2.getLeft());
00758
00759 nodes1.push(&node1);
00760 nodes2.push(node2.getRight());
00761 }
00762 }
00763 }
00764 }
00765
00766 if (normalise) {
00767 result1 /= p1.getTotalWeight();
00768 result2 /= p2.getTotalWeight();
00769 }
00770 }
00771 }
00772
00773 #endif
00774