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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <algorithm>
00042 #include <limits>
00043 #include <list>
00044 #include <sstream>
00045 #include <string>
00046 #include <vector>
00047
00048 #include <qgarlib/array.H>
00049 #include <qgarlib/math.H>
00050 #include <qgarlib/QgarErrorAlgorithm.H>
00051
00052
00053
00054 namespace qgar
00055 {
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 template <class T>
00070 GenCluster<T>::GenCluster(const std::vector<value_type>& elements,
00071 const_reference center)
00072
00073 : _center(center),
00074 _elements(elements)
00075
00076 {
00077
00078 }
00079
00080
00081 template <class T>
00082 GenCluster<T>::GenCluster(const GenCluster<T>& other)
00083
00084 : _center(other._center),
00085 _elements(other._elements)
00086
00087 {
00088
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 template <class T>
00098 GenCluster<T>&
00099 GenCluster<T>::operator=(const GenCluster<T>& rhs)
00100 {
00101 if (this != &rhs)
00102 {
00103 _center = rhs._center;
00104 _elements = rhs._elements;
00105 }
00106
00107 return *this;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116 template <class T>
00117 inline size_t
00118 GenCluster<T>::size() const
00119 {
00120 return _elements.size();
00121 }
00122
00123
00124 template <class T>
00125 inline const T&
00126 GenCluster<T>::center() const
00127 {
00128 return _center;
00129 }
00130
00131
00132 template <class T>
00133 inline const std::vector<T>&
00134 GenCluster<T>::elements() const
00135 {
00136 return _elements;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 template<class T>
00167 GenKMeans<T>::GenKMeans(const std::vector<T>& anObjVect,
00168 DistanceFunction aDistFunction,
00169 int aClusterCnt)
00170
00171 throw(QgarErrorAlgorithm)
00172
00173 : _clusterCnt(aClusterCnt),
00174 _clusterElts(aClusterCnt),
00175 _distance(aDistFunction)
00176
00177 {
00178 _objVect.reserve(anObjVect.size());
00179
00180 for (typename std::vector<T>::const_iterator it = anObjVect.begin();
00181 it != anObjVect.end();
00182 ++it)
00183 {
00184 _objVect.push_back(&(*it));
00185 }
00186
00187 PRIVATEinitCenters();
00188 PRIVATEgetClusters();
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 template<class T>
00200 GenKMeans<T>::GenKMeans(const std::vector<T>& anObjVect,
00201 DistanceFunction aDistFunction,
00202 const std::vector<T>& aCenterVector,
00203 int aClusterCnt)
00204
00205 throw(QgarErrorAlgorithm)
00206 : _clusterCnt(aClusterCnt),
00207 _clusterElts(aClusterCnt),
00208 _distance(aDistFunction)
00209
00210 {
00211 _objVect.reserve(anObjVect.size());
00212
00213 for(unsigned int i=0; i < anObjVect.size(); ++i)
00214 {
00215 _objVect.push_back(&anObjVect[i]);
00216 }
00217
00218 for (int idx = 0 ; idx < aClusterCnt ; idx++)
00219 {
00220 _clusterSizes.push_back(0);
00221 _clusterCenters.push_back(&aCenterVector[idx]);
00222 }
00223
00224 PRIVATEgetClusters();
00225 }
00226
00227
00228
00229
00230
00231
00232
00233 template<class T>
00234 GenKMeans<T>::~GenKMeans()
00235 {
00236
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 template<class T>
00248 inline int
00249 GenKMeans<T>::clusterCnt() const
00250 {
00251 return _clusterCnt;
00252 }
00253
00254
00255
00256
00257 template<class T>
00258 inline const std::vector<int>&
00259 GenKMeans<T>::clusterSizes() const
00260 {
00261 return _clusterSizes;
00262 }
00263
00264
00265
00266
00267 template<class T>
00268 inline const std::vector<const T*>&
00269 GenKMeans<T>::clusterCenters() const
00270 {
00271 return _clusterCenters;
00272 }
00273
00274
00275
00276
00277 template<class T>
00278 inline const std::vector< std::vector<const T*> >&
00279 GenKMeans<T>::accessClusterElts() const
00280 {
00281 return _clusterElts;
00282 }
00283
00284
00285
00286
00287 template<class T>
00288 inline std::vector< std::vector<const T*> >
00289 GenKMeans<T>::clusterElts() const
00290 {
00291 return _clusterElts;
00292 }
00293
00294
00295
00296
00297 template<class T>
00298 const std::vector< GenCluster<T> >&
00299 GenKMeans<T>::accessClusters() const
00300 {
00301 PRIVATEconsFinalClusters();
00302 return _clusters;
00303 }
00304
00305
00306
00307
00308 template<class T>
00309 std::vector< GenCluster<T> >
00310 GenKMeans<T>::clusters() const
00311 {
00312 PRIVATEconsFinalClusters();
00313 return _clusters;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 template <class T>
00326 void
00327 GenKMeans<T>::PRIVATEinitCenters()
00328
00329 throw(QgarErrorAlgorithm)
00330
00331 {
00332 typename std::vector<T const *>::iterator iterObjs
00333 = _objVect.begin();
00334
00335
00336
00337 int idx = 0;
00338 while (idx < _clusterCnt)
00339 {
00340 if (iterObjs == _objVect.end())
00341 {
00342
00343 std::ostringstream os;
00344 os << "Unable to get given number of initial clusters: "
00345 << _clusterCnt;
00346 throw QgarErrorAlgorithm(__FILE__, __LINE__,
00347 "template <class T> void qgar::GenKMeans<T>::PRIVATEinitCenters()",
00348 os.str());
00349 }
00350
00351
00352
00353
00354 bool sameCenter = false;
00355 for (int jdx = 0 ; jdx < idx ; jdx++)
00356 {
00357 if (qgEq0((*_distance)(*_clusterCenters[jdx], **iterObjs)))
00358 {
00359 sameCenter = true;
00360 break;
00361 }
00362 }
00363
00364 if (!sameCenter)
00365 {
00366
00367 _clusterCenters.push_back(*iterObjs);
00368
00369 _clusterSizes.push_back(0);
00370
00371 idx++;
00372 }
00373
00374 iterObjs++;
00375 }
00376
00377 }
00378
00379
00380
00381
00382
00383 template <class T>
00384 void
00385 GenKMeans<T>::PRIVATEdistributeIntoClusters()
00386 {
00387
00388 int idxMin = 0;
00389
00390
00391
00392 for(typename std::vector<const T*>::const_iterator
00393 iterObjs = _objVect.begin();
00394 iterObjs != _objVect.end();
00395 ++iterObjs)
00396 {
00397
00398 double distMin = std::numeric_limits<double>::max();
00399
00400
00401
00402 for(int idx = 0 ; idx < _clusterCnt ; ++idx)
00403 {
00404 double dist = (*_distance)(**iterObjs, *_clusterCenters[idx]);
00405 if (dist < distMin)
00406 {
00407 distMin = dist;
00408 idxMin = idx;
00409 }
00410 }
00411
00412
00413 _clusterElts[idxMin].push_back(*iterObjs);
00414 _clusterSizes[idxMin]++;
00415 }
00416
00417 }
00418
00419
00420
00421
00422
00423 template <class T>
00424 void
00425 GenKMeans<T>::PRIVATEgetCenters(std::vector<const T*>& aNewCenterVector)
00426
00427 throw(QgarErrorAlgorithm)
00428
00429 {
00430
00431
00432 for(int idxClu = 0 ; idxClu < _clusterCnt ; ++idxClu)
00433 {
00434 int sizeClu = _clusterSizes[idxClu];
00435 if (sizeClu == 0)
00436 {
00437 throw QgarErrorAlgorithm(__FILE__, __LINE__,
00438 "template <class T> void qgar::GenKMeans<T>::PRIVATEgetCenters(std::vector<const T*>&)",
00439 "At least one cluster is empty");
00440 }
00441 else
00442 {
00443
00444 std::vector<const T*>& pClu = _clusterElts[idxClu];
00445
00446
00447
00448
00449
00450
00451 double* distTab = new double[sizeClu];
00452 qgFill(distTab, sizeClu, 0.);
00453
00454
00455
00456 for(int idxObj = 0 ; idxObj < (sizeClu - 1) ; idxObj++)
00457 {
00458
00459 const T* currObj = (pClu)[idxObj];
00460
00461
00462
00463
00464 for(int jdxObj = idxObj + 1 ; jdxObj < sizeClu ; ++jdxObj)
00465 {
00466
00467 double dist = (*_distance)(*currObj, *(pClu)[jdxObj]);
00468 dist *= dist;
00469
00470 distTab[idxObj] += dist;
00471 distTab[jdxObj] += dist;
00472 }
00473
00474 }
00475
00476
00477
00478 aNewCenterVector[idxClu] = (pClu)[qgMinElement(distTab, sizeClu)];
00479
00480 delete [] distTab;
00481 }
00482
00483 }
00484
00485 }
00486
00487
00488
00489
00490
00491 template <class T>
00492 void
00493 GenKMeans<T>::PRIVATEgetClusters()
00494 {
00495
00496 std::vector<const T*> newCenterVector(_clusterCnt);
00497
00498
00499
00500 while (true)
00501 {
00502
00503 PRIVATEdistributeIntoClusters();
00504
00505
00506 PRIVATEgetCenters(newCenterVector);
00507
00508
00509 bool stable = true;
00510
00511
00512 for(int idx = 0 ; idx < _clusterCnt ; ++idx)
00513 {
00514 stable = stable && (_clusterCenters[idx] == newCenterVector[idx]);
00515 if (!stable)
00516 {
00517 break;
00518 }
00519 }
00520
00521 if (stable)
00522 {
00523 break;
00524 }
00525
00526
00527 for(int idx = 0 ; idx < _clusterCnt ; ++idx)
00528 {
00529
00530 std::vector<const T*>& pClu = _clusterElts[idx];
00531
00532
00533 pClu.erase(pClu.begin(), pClu.end());
00534
00535
00536 _clusterSizes[idx] = 0;
00537
00538
00539 _clusterCenters[idx] = newCenterVector[idx];
00540 }
00541
00542 }
00543
00544 }
00545
00546
00547
00548
00549
00550 template <class T>
00551 void
00552 GenKMeans<T>::PRIVATEconsFinalClusters()
00553 {
00554
00555
00556 if (_clusters.empty())
00557 {
00558
00559 for (int clusterIdx = 0; clusterIdx < _clusterCnt; ++clusterIdx)
00560 {
00561 std::vector<T> vect;
00562 vect.reserve(_clusterSizes[clusterIdx]);
00563
00564 for(int eltIdx = 0; eltIdx < _clusterSizes[clusterIdx]; ++eltIdx)
00565 {
00566 vect.push_back(*_clusterElts[clusterIdx][eltIdx]);
00567 }
00568
00569 _clusters.push_back(GenCluster<T>(vect, *_clusterCenters[clusterIdx]));
00570 }
00571
00572 }
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 template <class T>
00594 std::vector< GenCluster<T> >
00595 qgKMeans(const std::vector<T>& anObjVect,
00596 double (*aDistFunction)(const T&, const T&),
00597 int aClusterCnt)
00598
00599 throw (QgarErrorAlgorithm)
00600
00601 {
00602 return (GenKMeans<T>(anObjVect, aDistFunction, aClusterCnt)).clusters();
00603 }
00604
00605
00606
00607
00608
00609 template <class T>
00610 std::vector< GenCluster<T> >
00611 qgKMeans(const std::vector<T>& anObjVect,
00612 double (*aDistFunction) (const T&, const T&),
00613 std::vector<T*>& aCenterVector,
00614 int aClusterCnt)
00615
00616 throw (QgarErrorAlgorithm)
00617
00618 {
00619 return
00620 (GenKMeans<T>(anObjVect, aDistFunction, aCenterVector, aClusterCnt)).clusters();
00621 }
00622
00623
00624
00625
00626
00627
00628
00629 }