libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNkMedoids.h
Go to the documentation of this file.
1 /* Copyright 2014-2016 INSA-Lyon, ENS-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNkMedoids.h
19  * \author Yann LEYDIER
20  */
21 
22 #ifndef CRNkMedoids_HEADER
23 #define CRNkMedoids_HEADER
24 
25 #include <CRNException.h>
26 #include <vector>
27 #include <map>
28 #include <tuple>
29 #include <limits>
30 
31 namespace crn
32 {
36  namespace kmedoids
37  {
38  namespace init
39  {
46  struct Central
47  {
48  Central(size_t n_classes):k(n_classes) {}
49  std::vector<size_t> operator()(const std::vector<std::vector<double>> &distmat) const;
50  private:
51  size_t k;
52  };
53 
58  struct PAM
59  {
60  PAM(size_t n_classes):k(n_classes) {}
61  std::vector<size_t> operator()(const std::vector<std::vector<double>> &distmat) const;
62  private:
63  size_t k;
64  };
65  }
66  namespace update
67  {
72  struct Local
73  {
74  void operator()(std::vector<size_t> &medoids, const std::vector<std::multimap<double, size_t>> &clusters, const std::vector<std::vector<double>> &distmat) const;
75  };
76 
81  struct PAM
82  {
83  void operator()(std::vector<size_t> &medoids, const std::vector<std::multimap<double, size_t>> &clusters, const std::vector<std::vector<double>> &distmat) const;
84  };
85  }
86 
95  template<typename Init, typename Update> std::tuple<std::vector<size_t>, std::vector<std::multimap<double, size_t>>, std::vector<size_t>> Run(Init init, Update update, const std::vector<std::vector<double>> &distmat, size_t maxiter = std::numeric_limits<size_t>::max())
96  {
97  const auto nelem = distmat.size();
98  // check
99  for (const auto &row : distmat)
100  if (row.size() != nelem)
101  throw ExceptionDimension("kmedoids::Run(): The distance matrix is not square.");
102  // init
103  auto medoids = init(distmat);
104  const auto k = medoids.size();
105  /*
106  std::cout << "init: ";
107  for (auto m : medoids)
108  std::cout << m << " ";
109  std::cout << std::endl;
110  */
111  // run
112  auto clusters = std::vector<std::multimap<double, size_t>>(k);
113  auto distsum = 0.0, precsum = std::numeric_limits<double>::max();
114  auto iter = size_t{0};
115  while (precsum != distsum)
116  {
117  precsum = distsum;
118  distsum = 0.0;
119  // classification
120  std::vector<std::multimap<double, size_t>>(k).swap(clusters);
121  for (auto o = size_t(0); o < nelem; ++o)
122  {
123  auto ndist = std::numeric_limits<double>::max();
124  auto nclass = size_t{0};
125  for (auto m = size_t(0); m < k; ++m)
126  if (distmat[o][medoids[m]] < ndist)
127  {
128  ndist = distmat[o][medoids[m]];
129  nclass = m;
130  }
131  clusters[nclass].insert(std::make_pair(ndist, o));
132  distsum += ndist;
133  }
134  // update
135  update(medoids, clusters, distmat);
136 
137  if (++iter >= maxiter)
138  break;
139  }
140  auto classnum = std::vector<size_t>(nelem, 0);
141  for (auto c = size_t(0); c < k; ++c)
142  for (const auto &o : clusters[c])
143  classnum[o.second] = c;
144  return std::make_tuple(std::move(classnum), std::move(clusters), std::move(medoids));
145  }
146  }
147 }
148 
149 #endif
std::vector< size_t > operator()(const std::vector< std::vector< double >> &distmat) const
Definition: CRNkMedoids.cpp:57
void operator()(std::vector< size_t > &medoids, const std::vector< std::multimap< double, size_t >> &clusters, const std::vector< std::vector< double >> &distmat) const
Definition: CRNkMedoids.cpp:98
Finds the k most central elements.
Definition: CRNkMedoids.h:46
PAM(size_t n_classes)
Definition: CRNkMedoids.h:60
std::vector< size_t > operator()(const std::vector< std::vector< double >> &distmat) const
Definition: CRNkMedoids.cpp:30
void operator()(std::vector< size_t > &medoids, const std::vector< std::multimap< double, size_t >> &clusters, const std::vector< std::vector< double >> &distmat) const
A dimension error.
Definition: CRNException.h:119
Gets the element with the lower distance to other elements in the cluster.
Definition: CRNkMedoids.h:72
std::tuple< std::vector< size_t >, std::vector< std::multimap< double, size_t > >, std::vector< size_t > > Run(Init init, Update update, const std::vector< std::vector< double >> &distmat, size_t maxiter=std::numeric_limits< size_t >::max())
k medoids
Definition: CRNkMedoids.h:95
Central(size_t n_classes)
Definition: CRNkMedoids.h:48