00001 #ifndef INDII_ML_AUX_KDTREE_HPP
00002 #define INDII_ML_AUX_KDTREE_HPP
00003
00004 #include "PartitionTree.hpp"
00005 #include "KDTreeNode.hpp"
00006 #include "MedianPartitioner.hpp"
00007
00008 #include "boost/serialization/split_member.hpp"
00009
00010 #include <vector>
00011
00012 namespace indii {
00013 namespace ml {
00014 namespace aux {
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 template <class ST = MedianPartitioner>
00032 class KDTree : public PartitionTree {
00033 public:
00034
00035
00036
00037
00038
00039
00040 KDTree();
00041
00042
00043
00044
00045
00046
00047 KDTree(DiracMixturePdf* p);
00048
00049
00050
00051
00052 KDTree(const KDTree<ST>& o);
00053
00054
00055
00056
00057 virtual ~KDTree();
00058
00059 virtual PartitionTree* clone();
00060
00061
00062
00063
00064 KDTree<ST>& operator=(const KDTree<ST>& o);
00065
00066 virtual PartitionTreeNode* getRoot();
00067
00068 virtual void setRoot(PartitionTreeNode* root);
00069
00070 private:
00071
00072
00073
00074 KDTreeNode* root;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static KDTreeNode* build(DiracMixturePdf* p,
00087 const std::vector<unsigned int>& is, const unsigned int depth = 0);
00088
00089
00090
00091
00092 template<class Archive>
00093 void save(Archive& ar, const unsigned int version) const;
00094
00095
00096
00097
00098 template<class Archive>
00099 void load(Archive& ar, const unsigned int version);
00100
00101
00102
00103
00104 BOOST_SERIALIZATION_SPLIT_MEMBER()
00105 friend class boost::serialization::access;
00106
00107 };
00108
00109 }
00110 }
00111 }
00112
00113 #include "boost/serialization/base_object.hpp"
00114
00115 template<class ST>
00116 indii::ml::aux::KDTree<ST>::KDTree() : root(NULL) {
00117
00118 }
00119
00120 template<class ST>
00121 indii::ml::aux::KDTree<ST>::KDTree(DiracMixturePdf* p) : PartitionTree(p) {
00122 unsigned int i;
00123 std::vector<unsigned int> is(p->getSize());
00124
00125 for (i = 0; i < is.size(); i++) {
00126 is[i] = i;
00127 }
00128
00129 if (is.size() > 0) {
00130 root = build(p, is);
00131 } else {
00132 root = NULL;
00133 }
00134 }
00135
00136 template<class ST>
00137 indii::ml::aux::KDTree<ST>::KDTree(const KDTree<ST>& o) :
00138 PartitionTree(o) {
00139 if (o.root == NULL) {
00140 root = NULL;
00141 } else {
00142 root = dynamic_cast<KDTreeNode*>(o.root->clone());
00143 }
00144 }
00145
00146 template<class ST>
00147 indii::ml::aux::KDTree<ST>::~KDTree() {
00148 delete root;
00149 }
00150
00151 template<class ST>
00152 indii::ml::aux::KDTree<ST>& indii::ml::aux::KDTree<ST>::operator=(
00153 const KDTree<ST>& o) {
00154 PartitionTree::operator=(o);
00155
00156 delete root;
00157 if (o.root == NULL) {
00158 root = NULL;
00159 } else {
00160 root = dynamic_cast<KDTreeNode*>(o.root->clone());
00161 }
00162
00163 return *this;
00164 }
00165
00166 template<class ST>
00167 indii::ml::aux::PartitionTree* indii::ml::aux::KDTree<ST>::clone() {
00168 return new KDTree<ST>(*this);
00169 }
00170
00171 template<class ST>
00172 inline indii::ml::aux::PartitionTreeNode*
00173 indii::ml::aux::KDTree<ST>::getRoot() {
00174 return root;
00175 }
00176
00177 template<class ST>
00178 void indii::ml::aux::KDTree<ST>::setRoot(PartitionTreeNode* root) {
00179 this->root = dynamic_cast<KDTreeNode*>(root);
00180 }
00181
00182 template<class ST>
00183 indii::ml::aux::KDTreeNode* indii::ml::aux::KDTree<ST>::build(
00184 DiracMixturePdf* p, const std::vector<unsigned int>& is,
00185 const unsigned int depth) {
00186
00187 assert (is.size() > 0);
00188
00189 KDTreeNode* result;
00190 unsigned int i;
00191
00192 if (is.size() == 1) {
00193
00194 result = new KDTreeNode(p, is.front(), depth);
00195 } else {
00196
00197 ST partitioner;
00198
00199 if (partitioner.init(p, is)) {
00200 std::vector<unsigned int> ls, rs;
00201 KDTreeNode *left, *right;
00202
00203 ls.reserve(is.size() / 2);
00204 rs.reserve(is.size() / 2);
00205
00206 for (i = 0; i < is.size(); i++) {
00207 if (partitioner.assign(p->get(is[i])) == Partitioner::LEFT) {
00208 ls.push_back(is[i]);
00209 } else {
00210 rs.push_back(is[i]);
00211 }
00212 }
00213
00214 if (ls.size() == 0) {
00215
00216 result = new KDTreeNode(p, rs, depth);
00217 } else if (rs.size() == 0) {
00218
00219 result = new KDTreeNode(p, ls, depth);
00220 } else {
00221
00222 left = build(p, ls, depth + 1);
00223 right = build(p, rs, depth + 1);
00224
00225 result = new KDTreeNode(left, right, depth);
00226 }
00227 } else {
00228
00229
00230
00231 result = new KDTreeNode(p, is, depth);
00232 }
00233 }
00234
00235 return result;
00236 }
00237
00238 template<class ST>
00239 template<class Archive>
00240 void indii::ml::aux::KDTree<ST>::save(Archive& ar,
00241 const unsigned int version) const {
00242 ar & boost::serialization::base_object<PartitionTree>(*this);
00243
00244 const bool haveRoot = (root != NULL);
00245 ar & haveRoot;
00246 if (haveRoot) {
00247 ar & root;
00248 }
00249 }
00250
00251 template<class ST>
00252 template<class Archive>
00253 void indii::ml::aux::KDTree<ST>::load(Archive& ar,
00254 const unsigned int version) {
00255 bool haveRoot = false;
00256
00257 if (root != NULL) {
00258 delete root;
00259 root = NULL;
00260 }
00261
00262 ar & boost::serialization::base_object<PartitionTree>(*this);
00263 ar & haveRoot;
00264 if (haveRoot) {
00265 ar & root;
00266 }
00267 }
00268
00269 #endif
00270