2 #include <hpda/common/common.h>
7 template <
typename Po
intType,
typename DistanceType>
struct euclidean {
8 static DistanceType distance_square(
const PointType &p1,
10 static_assert(
sizeof(PointType) == -1,
11 "You have to have a specialization for euclidean distance "
13 return DistanceType();
19 template <
typename Po
intIteratorType,
typename Po
intType>
22 static PointType point(
const PointIteratorType &p) {
return *p; }
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>
35 typedef PointContainer points_t;
36 loyd_impl(
const PointIteratorType &points_begin,
37 const PointIteratorType &points_end,
const points_t &initial,
int k,
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());
47 if (m_means.size() != m_k) {
48 throw std::runtime_error(
"loyd, inconsistent point number");
50 for (
int i = 0; i < m_k; ++i) {
51 m_clusters.push_back(point_refs_t());
54 while (!is_all_means_close_enough()) {
57 for (
int i = 0; i < m_k; ++i) {
58 m_clusters[i].clear();
61 for (PointIteratorType i = m_begin; i != m_end; i++) {
65 m_last_means = m_means;
66 for (
int i = 0; i < m_k; ++i) {
68 for (
int j = 0; j < m_clusters[i].size(); ++j) {
69 p = p + PointTraitsType::point(m_clusters[i][j]);
71 p = p / m_clusters[i].size();
77 points_t means()
const {
return m_means; }
78 int round()
const {
return m_round; }
82 std::vector<std::vector<PointIteratorType>> &clusters() {
return m_clusters; }
85 bool is_all_means_close_enough() {
86 for (
int i = 0; i < m_k; i++) {
88 m_means[i], m_last_means[i]);
96 void assign(
const PointIteratorType &p) {
97 DistanceType min = std::numeric_limits<DistanceType>::max();
99 for (
int i = 0; i < m_means.size(); ++i) {
101 PointTraitsType::point(p), m_means[i]);
107 m_clusters[index].push_back(p);
111 PointIteratorType m_begin;
112 PointIteratorType m_end;
114 DistanceType m_delta;
117 typedef std::vector<PointIteratorType> point_refs_t;
118 std::vector<point_refs_t> m_clusters;
120 points_t m_last_means;
123 template <
typename PointIteratorType,
typename PointType,
typename DistanceType,
124 typename PointTraitsType,
typename PointContainer>
125 class loyd_impl<PointIteratorType, PointType, DistanceType, PointTraitsType,
126 PointContainer, false> {
128 sizeof(PointIteratorType) == -1,
129 "point container type should be for point type, not other type");