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 #ifndef CBINARYRELATION_H_
00029 #define CBINARYRELATION_H_
00030 #include <mrpt/math/CMatrixTemplate.h>
00031
00032 #include <set>
00033 #include <iterator>
00034 #include <algorithm>
00035 #include <utility>
00036
00037 namespace mrpt { namespace math {
00038
00039
00040
00041 template<typename T,typename U,bool UIsObject> class CBinaryRelation;
00042 namespace detail
00043 {
00044
00045
00046
00047
00048 template<typename U,bool B> class MatrixWrapper;
00049
00050
00051 template<typename U> class MatrixWrapper<U,true> {
00052 public:
00053 typedef CMatrixTemplateObjects<U> MatrixType;
00054 };
00055 template<typename U> class MatrixWrapper<U,false> {
00056 public:
00057 typedef CMatrixTemplate<U> MatrixType;
00058 };
00059
00060 template<typename T,typename U,bool UIsObject,typename FunctionType> inline void applyFunction(CBinaryRelation<T,U,UIsObject> &o, FunctionType fun,size_t e1,size_t e2,const T &T1,const T &T2);
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070 template<typename T,typename U,bool UIsObject=false> class CBinaryRelation {
00071 private:
00072
00073
00074 typedef typename detail::MatrixWrapper<U,UIsObject>::MatrixType MatrixType;
00075 public:
00076 typedef U (*SimpleFunctionByReturnValue)(T,T);
00077 typedef U (*FunctionByReturnValue)(const T &,const T &);
00078 typedef void (*FunctionByReferencePass)(const T &,const T &,U &);
00079 typedef typename std::set<T>::const_iterator const_iterator;
00080 typedef typename std::set<T>::const_reverse_iterator const_reverse_iterator;
00081 typedef CMatrixRowAccessor<U> AccessorForFirstElement;
00082 typedef CMatrixColumnAccessor<U> AccessorForSecondElement;
00083 typedef CConstMatrixRowAccessor<U> ConstAccessorForFirstElement;
00084 typedef CConstMatrixColumnAccessor<U> ConstAccessorForSecondElement;
00085 private:
00086 std::set<T> elements;
00087 MatrixType relation;
00088
00089
00090
00091
00092
00093 template<typename FunctionType> inline void applyFunction(FunctionType fun,size_t e1,size_t e2,const T &T1,const T &T2) {
00094 detail::applyFunction<T,U,UIsObject,FunctionType>(*this,fun,e1,e2,T1,T2);
00095 }
00096
00097 public:
00098
00099
00100
00101 explicit inline CBinaryRelation(const std::set<T> &els):elements(els),relation(els.size(),els.size()) {}
00102
00103
00104
00105 template<typename FunctionType> inline CBinaryRelation(const std::set<T> &els,FunctionType fun):elements(els),relation(els.size(),els.size()) {
00106 initializeWith(fun);
00107 }
00108
00109
00110
00111 template<typename FunctionType> void initializeWith(FunctionType fun) {
00112 typename std::set<T>::const_iterator it=elements.begin();
00113 for (size_t i=0;i<elements.size();++i,++it) {
00114 typename std::set<T>::const_iterator jt=elements.begin();
00115 for (size_t j=0;j<elements.size();++j,++jt) applyFunction(fun,i,j,*it,*jt);
00116 }
00117 }
00118
00119
00120
00121 template<typename FunctionType> void initializeSymmetricallyWith(FunctionType fun) {
00122 typename std::set<T>::const_iterator it=elements.begin();
00123 for (size_t i=0;i<elements.size();++i,++it) {
00124 applyFunction(fun,i,i,*it,*it);
00125 typename std::set<T>::const_iterator jt=it;
00126 jt++;
00127 for (size_t j=i+1;j<elements.size();++j,++jt) {
00128 applyFunction(fun,i,j,*it,*jt);
00129 relation(j,i)=relation(i,j);
00130 }
00131 }
00132 }
00133
00134
00135
00136 inline void setRelationValue(size_t e1,size_t e2,const U &newVal) {
00137 relation.get_unsafe(e1,e2)=newVal;
00138 }
00139
00140
00141
00142 inline const U &getRelationValue(size_t e1,size_t e2) const {
00143 return relation.get_unsafe(e1,e2);
00144 }
00145 inline const U &operator()(size_t e1,size_t e2) const {
00146 return getRelationValue(e1,e2);
00147 }
00148
00149
00150
00151 inline U &getRelationValue(size_t e1,size_t e2) {
00152 return relation.get_unsafe(e1,e2);
00153 }
00154 inline U &operator()(size_t e1,size_t e2) {
00155 return getRelationValue(e1,e2);
00156 }
00157
00158
00159
00160 inline bool setRelationValue(const T &t1,const T &t2,const U &newVal) {
00161 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00162 typename std::set<T>::const_iterator it1=std::find(b,e,t1),it2=std::find(b,e,t2);
00163 if (it1==e||it2==e) return false;
00164 setRelationValue(static_cast<size_t>(std::distance(b,it1)),static_cast<size_t>(std::distance(b,it2)),newVal);
00165 return true;
00166 }
00167
00168
00169
00170 inline U getRelationValue(const T &t1,const T &t2) const {
00171 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00172 typename std::set<T>::const_iterator it1=std::find(b,e,t1),it2=std::find(b,e,t2);
00173 if (it1==e||it2==e) throw std::domain_error("Element not found");
00174 return getRelationValue(static_cast<size_t>(std::distance(b,it1)),static_cast<size_t>(std::distance(b,it2)));
00175 }
00176
00177
00178
00179
00180 inline U &getRelationValue(const T &t1,const T &t2) {
00181 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00182 typename std::set<T>::const_iterator it1=std::find(b,e,t1),it2=std::find(b,e,t2);
00183 if (it1==e||it2==e) throw std::domain_error("Element not found");
00184 return getRelationValue(static_cast<size_t>(std::distance(b,it1)),static_cast<size_t>(distance(b,it2)));
00185 }
00186
00187
00188
00189 inline const_iterator begin() const {
00190 return elements.begin();
00191 }
00192
00193
00194
00195 inline const_iterator end() const {
00196 return elements.end();
00197 }
00198
00199
00200
00201 inline const_reverse_iterator rbegin() const {
00202 return elements.rbegin();
00203 }
00204
00205
00206
00207 inline const_reverse_iterator rend() const {
00208 return elements.rend();
00209 }
00210
00211
00212
00213 T operator[](size_t i) const {
00214 ASSERT_(i<elements.size());
00215 typename std::set<T>::const_iterator it=elements.begin();
00216 std::advance(it,i);
00217 return *it;
00218 }
00219
00220
00221
00222 inline AccessorForFirstElement getRelationFrom(size_t i) {
00223 return AccessorForFirstElement(relation,i);
00224 }
00225
00226
00227
00228 inline ConstAccessorForFirstElement getRelationFrom(size_t i) const {
00229 return ConstAccessorForFirstElement(relation,i);
00230 }
00231
00232
00233
00234 inline AccessorForSecondElement getRelationTo(size_t i) {
00235 return AccessorForSecondElement(relation,i);
00236 }
00237
00238
00239
00240 inline ConstAccessorForSecondElement getRelationTo(size_t i) const {
00241 return ConstAccessorForSecondElement(relation,i);
00242 }
00243
00244
00245
00246 inline AccessorForFirstElement getRelationFrom(const T &t) {
00247 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00248 typename std::set<T>::const_iterator it=std::find(b,e,t);
00249 if (it==e) throw std::domain_error("Element not found");
00250 return getRelationFrom(static_cast<size_t>(std::distance(b,it)));
00251 }
00252
00253
00254
00255
00256 inline ConstAccessorForFirstElement getRelationFrom(const T &t) const {
00257 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00258 typename std::set<T>::const_iterator it=std::find(b,e,t);
00259 if (it==e) throw std::domain_error("Element not found");
00260 return getRelationFrom(static_cast<size_t>(std::distance(b,it)));
00261 }
00262 inline void getRelationFrom(size_t i,vector<U> &vec) {
00263 size_t N=elements.size();
00264 ASSERT_(i<N);
00265 vec.resize(N);
00266 ConstAccessorForFirstElement access(relation,i);
00267 std::copy(access.begin(),access.end(),vec.begin());
00268 }
00269 inline void getRelationFrom(const T &t,vector<U> &vec) {
00270 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00271 typename std::set<T>::const_iterator it=std::find(b,e,t);
00272 if (it==e) throw std::domain_error("Element not found");
00273 getRelationFrom(static_cast<size_t>(std::distance(b,it)),vec);
00274 }
00275
00276
00277
00278 inline AccessorForSecondElement getRelationTo(const T &t) {
00279 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00280 typename std::set<T>::const_iterator it=std::find(b,e,t);
00281 if (it==e) throw std::domain_error("Element not found");
00282 return getRelationTo(static_cast<size_t>(std::distance(b,it)));
00283 }
00284
00285
00286
00287
00288 inline ConstAccessorForSecondElement getRelationTo(const T &t) const {
00289 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00290 typename std::set<T>::const_iterator it=std::find(b,e,t);
00291 if (it==e) throw std::domain_error("Element not found");
00292 return getRelationTo(static_cast<size_t>(std::distance(b,it)));
00293 }
00294 inline void getRelationTo(size_t i,vector<U> &vec) {
00295 size_t N=elements.size();
00296 ASSERT_(i<N);
00297 vec.resize(N);
00298 ConstAccessorForSecondElement access(relation,i);
00299 std::copy(access.begin(),access.end(),vec.begin());
00300 }
00301 inline void getRelationTo(const T &t,vector<U> &vec) {
00302 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00303 typename std::set<T>::const_iterator it=std::find(b,e,t);
00304 if (it==e) throw std::domain_error("Element not found");
00305 getRelationTo(static_cast<size_t>(std::distance(b,it)),vec);
00306 }
00307
00308
00309
00310 void removeElementAt(size_t i) {
00311 ASSERT_(i<elements.size());
00312 typename std::set<T>::const_iterator it=elements.begin();
00313 std::advance(it,i);
00314 elements.erase(i);
00315 set<size_t> ii;
00316 ii.insert(i);
00317 relation.removeRowsAndCols(ii,ii);
00318 }
00319
00320
00321
00322 bool removeElement(const T &el) {
00323 typename std::set<T>::const_iterator b=elements.begin(),e=elements.end();
00324 typename std::set<T>::const_iterator it=std::find(e,b,el);
00325 if (it==e) return false;
00326 removeElementAt(std::distance(b,it));
00327 return true;
00328 }
00329
00330
00331
00332 size_t removeElements(const set<T> &vals) {
00333 set<size_t> positions;
00334 for (typename set<T>::const_iterator it=vals.begin();it!=vals.end();++it) {
00335 typename set<T>::iterator elsIt=std::find(elements.begin(),elements.end(),*it);
00336 if (elsIt!=elements.end()) positions.insert(std::distance(elements.begin(),elsIt));
00337 }
00338
00339
00340
00341
00342
00343
00344 removeElementsAt(positions);
00345 return positions.size();
00346 }
00347 void removeElementsAt(const set<size_t> &poss) {
00348 relation.removeRowsAndCols(poss,poss);
00349 for (set<size_t>::const_reverse_iterator it=poss.rbegin();it!=poss.rend();++it) {
00350 typename std::set<T>::const_iterator it2=elements.begin();
00351 std::advance(it2,*it);
00352 elements.erase(it2);
00353 }
00354 }
00355
00356
00357
00358
00359 std::pair<bool,size_t> insertElement(const T &el) {
00360 std::pair<typename std::set<T>::iterator,bool> ins=elements.insert(el);
00361 size_t dist=std::distance(elements.begin(),ins.first);
00362 if (ins.second) {
00363 std::multiset<size_t> newEls;
00364 newEls.insert(dist);
00365 relation.insertRowsAndCols(newEls,newEls);
00366 return std::make_pair(true,dist);
00367 } else return std::make_pair(false,dist);
00368 }
00369
00370
00371
00372 template<typename FunctionType> std::pair<bool,size_t> insertElement(const T &el,FunctionType fun) {
00373 std::pair<bool,size_t> ins=insertElement(el);
00374 size_t pos=ins.second;
00375 for (size_t i=0;i<elements.size();++i) {
00376 const T &newEl=operator[](i);
00377 applyFunction(fun,pos,i,el,newEl);
00378 applyFunction(fun,i,pos,newEl,el);
00379 }
00380 return ins;
00381 }
00382
00383
00384
00385 size_t insertElements(const std::set<T> &els) {
00386 if (els.empty()) return 0;
00387
00388
00389
00390 std::vector<size_t> added;
00391
00392 added.reserve(els.size());
00393 for (typename std::set<T>::const_iterator it=els.begin();it!=els.end();++it) {
00394 std::pair<typename std::set<T>::iterator,bool> ins=elements.insert(*it);
00395 size_t dist=std::distance(elements.begin(),ins.first);
00396 if (ins.second) {
00397 added.push_back(dist);
00398 for (std::vector<size_t>::iterator it2=added.begin();it2!=added.end();++it2) if (*it2>=dist) ++(*it2);
00399
00400 }
00401 }
00402 std::sort(added.begin(),added.end());
00403 for (size_t j=1;j<added.size();++j) added[j]-=j;
00404 std::multiset<size_t> poss(added.begin(),added.end());
00405 relation.insertRowsAndCols(poss,poss);
00406 return added.size();
00407 }
00408
00409
00410
00411 template<typename FunctionType> size_t insertElements(const std::set<T> &els,FunctionType fun) {
00412 if (els.empty()) return 0;
00413 size_t howMany=insertElements(els);
00414 std::set<size_t> poss;
00415 {
00416
00417 typename std::set<T>::const_iterator begin=elements.begin(),end=elements.end();
00418 for (typename std::set<T>::const_iterator it=els.begin();it!=els.end();++it) poss.insert(std::distance(begin,find(begin,end,*it)));
00419 }
00420 std::set<size_t> nPoss;
00421 std::set<size_t>::const_iterator begin=poss.begin(),end=poss.end();
00422 for (size_t i=0;i<elements.size();++i) if (std::find(begin,end,i)==end) nPoss.insert(i);
00423 vector<const T *> proxy;
00424 proxy.reserve(poss.size());
00425 for (std::set<size_t>::const_iterator it=begin;it!=end;++it) {
00426 const T &e1=operator[](*it);
00427 proxy.push_back(&e1);
00428 size_t i=0;
00429 for (typename std::set<T>::const_iterator it2=elements.begin();it2!=elements.end();++it2,++i) applyFunction(fun,*it,i,e1,*it2);
00430 }
00431 for (std::set<size_t>::const_iterator it=nPoss.begin();it!=nPoss.end();++it) {
00432 const T &e1=operator[](*it);
00433 typename std::vector<const T *>::const_iterator itV=proxy.begin();
00434 for (std::set<size_t>::const_iterator it2=poss.begin();it2!=poss.end();++it2,++itV) applyFunction(fun,*it,*it2,e1,**itV);
00435 }
00436 return howMany;
00437 }
00438
00439
00440
00441 void setElements(const std::set<T> &newEls) {
00442 relation.setSize(0,0);
00443 elements=newEls;
00444 relation.setSize(newEls.size(),newEls.size());
00445 }
00446
00447
00448
00449 inline size_t size() const {
00450 return elements.size();
00451 }
00452 };
00453
00454 namespace detail {
00455
00456 template<typename T,typename U,bool UIsObject,typename FunctionType> inline void applyFunction(CBinaryRelation<T,U,UIsObject> &o, FunctionType fun,size_t e1,size_t e2,const T &T1,const T &T2) {
00457 o.getRelationValue(e1,e2)=fun(T1,T2);
00458 }
00459
00460
00461
00462 template<typename T,typename U,bool UIsObject> inline void applyFunction(CBinaryRelation<T,U,UIsObject> &o,typename CBinaryRelation<T,U,UIsObject>::FunctionByReferencePass fun,size_t e1,size_t e2,const T &T1,const T &T2) {
00463 fun(T1,T2,o.getRelationValue(e1,e2));
00464 }
00465 }
00466
00467
00468 }}
00469 #endif