YPC  0.2.0
kmeans_loyd.h
1 #pragma once
2 #include <hpda/common/common.h>
3 #include <limits>
4 #include <type_traits>
5 
6 namespace hpda {
7 template <typename PointType, typename DistanceType> struct euclidean {
8  static DistanceType distance_square(const PointType &p1,
9  const PointType &p2) {
10  static_assert(sizeof(PointType) == -1,
11  "You have to have a specialization for euclidean distance "
12  "your point type");
13  return DistanceType();
14  }
15 };
16 
17 namespace algorithm {
18 namespace kmeans {
19 template <typename PointIteratorType, typename PointType>
21 public:
22  static PointType point(const PointIteratorType &p) { return *p; }
23 };
24 
25 namespace internal {
26 
27 template <typename PointIteratorType, typename PointType, typename DistanceType,
28  typename PointTraitsType =
30  typename PointContainer = std::vector<PointType>,
31  bool PointContainerChecker = std::is_same<
32  typename PointContainer::value_type, PointType>::value>
33 class loyd_impl {
34 public:
35  typedef PointContainer points_t;
36  loyd_impl(const PointIteratorType &points_begin,
37  const PointIteratorType &points_end, const points_t &initial, int k,
38  DistanceType delta)
39  : m_begin(points_begin), m_end(points_end), m_means(initial), m_k(k),
40  m_delta(delta * delta) {
41  for (int i = 0; i < k; ++i) {
42  m_last_means.push_back(PointType());
43  }
44  }
45 
46  void run() {
47  if (m_means.size() != m_k) {
48  throw std::runtime_error("loyd, inconsistent point number");
49  }
50  for (int i = 0; i < m_k; ++i) {
51  m_clusters.push_back(point_refs_t());
52  }
53  m_round = 0;
54  while (!is_all_means_close_enough()) {
55 
56  m_round++;
57  for (int i = 0; i < m_k; ++i) {
58  m_clusters[i].clear();
59  }
60 
61  for (PointIteratorType i = m_begin; i != m_end; i++) {
62  assign(i);
63  }
64 
65  m_last_means = m_means;
66  for (int i = 0; i < m_k; ++i) {
67  PointType p;
68  for (int j = 0; j < m_clusters[i].size(); ++j) {
69  p = p + PointTraitsType::point(m_clusters[i][j]);
70  }
71  p = p / m_clusters[i].size();
72  m_means[i] = p;
73  }
74  }
75  }
76 
77  points_t means() const { return m_means; }
78  int round() const { return m_round; }
79 
80  // DistanceType average_distance() const{}
81 
82  std::vector<std::vector<PointIteratorType>> &clusters() { return m_clusters; }
83 
84 protected:
85  bool is_all_means_close_enough() {
86  for (int i = 0; i < m_k; i++) {
88  m_means[i], m_last_means[i]);
89  if (d >= m_delta) {
90  return false;
91  }
92  }
93  return true;
94  }
95 
96  void assign(const PointIteratorType &p) {
97  DistanceType min = std::numeric_limits<DistanceType>::max();
98  int index;
99  for (int i = 0; i < m_means.size(); ++i) {
101  PointTraitsType::point(p), m_means[i]);
102  if (d < min) {
103  index = i;
104  min = d;
105  }
106  }
107  m_clusters[index].push_back(p);
108  }
109 
110 protected:
111  PointIteratorType m_begin;
112  PointIteratorType m_end;
113  int m_k;
114  DistanceType m_delta;
115  int m_round;
116 
117  typedef std::vector<PointIteratorType> point_refs_t;
118  std::vector<point_refs_t> m_clusters;
119  points_t m_means;
120  points_t m_last_means;
121 };
122 
123 template <typename PointIteratorType, typename PointType, typename DistanceType,
124  typename PointTraitsType, typename PointContainer>
125 class loyd_impl<PointIteratorType, PointType, DistanceType, PointTraitsType,
126  PointContainer, false> {
127  static_assert(
128  sizeof(PointIteratorType) == -1,
129  "point container type should be for point type, not other type");
130 };
131 
132 } // namespace internal
133 } // namespace kmeans
134 } // namespace algorithm
135 } // namespace hpda
hpda::euclidean
Definition: enclave_iris_parser.h:18
hpda::algorithm::kmeans::internal::loyd_impl
Definition: kmeans_loyd.h:33
hpda::algorithm::kmeans::direct_point_traits
Definition: kmeans_loyd.h:20