flspp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flspp-0.1.0/PKG-INFO +115 -0
- flspp-0.1.0/README.md +98 -0
- flspp-0.1.0/build.py +46 -0
- flspp-0.1.0/flspp/__init__.py +3 -0
- flspp-0.1.0/flspp/_core.cpp +109 -0
- flspp-0.1.0/flspp/additional_vector_stuff.h +39 -0
- flspp-0.1.0/flspp/clustering.cpp +70 -0
- flspp-0.1.0/flspp/clustering.h +56 -0
- flspp-0.1.0/flspp/clustering_algorithm.cpp +1964 -0
- flspp-0.1.0/flspp/clustering_algorithm.h +304 -0
- flspp-0.1.0/flspp/core.py +118 -0
- flspp-0.1.0/flspp/makros.cpp +8 -0
- flspp-0.1.0/flspp/makros.h +19 -0
- flspp-0.1.0/flspp/random_generator.cpp +18 -0
- flspp-0.1.0/flspp/random_generator.h +39 -0
- flspp-0.1.0/pyproject.toml +41 -0
- flspp-0.1.0/setup.py +31 -0
flspp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: flspp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary:
|
|
5
|
+
Author: Lukas Drexler
|
|
6
|
+
Author-email: lukas.drexler@hhu.de
|
|
7
|
+
Requires-Python: >=3.9,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
|
14
|
+
Requires-Dist: scikit-learn (>=1.4.2,<2.0.0)
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
[](https://github.com/algo-hhu/FLSpp/actions)
|
|
18
|
+
[](https://opensource.org/licenses/MIT)
|
|
19
|
+
[](https://www.python.org/downloads/release/python-390/)
|
|
20
|
+
[](https://pypi.org/project/flspp/)
|
|
21
|
+
|
|
22
|
+
# FLS++
|
|
23
|
+
|
|
24
|
+
An implementation of the FLS++ algorithm for k-means Clustering, as presented in [1]. This is an improvement of the LS++ algorithm presented by Lattanzi and Sohler in [2].
|
|
25
|
+
|
|
26
|
+
One can think of the algorithm as working in 3 phases:
|
|
27
|
+
|
|
28
|
+
1. Initializing centers with k-means++ (as presented in [3]).
|
|
29
|
+
2. Improving the center set by performing local search swaps (for details, see [1]).
|
|
30
|
+
3. Converging the solution with LLoyd's algorithm (also known as "the" k-means algorithm).
|
|
31
|
+
|
|
32
|
+
In [2] it is shown that `O(k log log k)` local search iterations yield a constant factor approximation. However, in both [1] and [2] it is shown that, in practice, a very small number of iterations (e.g. 20) already yields very good results, at very reasonable runtime.
|
|
33
|
+
|
|
34
|
+
The interface is built in the same way as scikit-learn's KMeans for better compatibility.
|
|
35
|
+
|
|
36
|
+
## References
|
|
37
|
+
|
|
38
|
+
[1] Theo Conrads, Lukas Drexler, Joshua Könen, Daniel R. Schmidt and Melanie Schmidt. "Local Search k-means++ with Foresight" (2024)
|
|
39
|
+
|
|
40
|
+
[2] Silvio Lattanzi and Christian Sohler. A better k-means++ algorithm via local search. In Proc.444
|
|
41
|
+
of the 36th ICML, volume 97 of Proceedings of Machine Learning Research, pages 3662–3671.445
|
|
42
|
+
PMLR, 09–15 Jun 2019
|
|
43
|
+
|
|
44
|
+
[3] David Arthur and Sergei Vassilvitskii. K-means++: The advantages of careful seeding. In409
|
|
45
|
+
Proceedings of the 18th SODA, page 1027–1035, USA, 2007
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install flspp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Example
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from flspp import FLSpp
|
|
57
|
+
|
|
58
|
+
example_data = [
|
|
59
|
+
[1.0, 1.0, 1.0],
|
|
60
|
+
[1.1, 1.1, 1.1],
|
|
61
|
+
[1.2, 1.2, 1.2],
|
|
62
|
+
[2.0, 2.0, 2.0],
|
|
63
|
+
[2.1, 2.1, 2.1],
|
|
64
|
+
[2.2, 2.2, 2.2],
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
flspp = FLSpp(n_clusters=2)
|
|
68
|
+
labels = flspp.fit_predict(example_data)
|
|
69
|
+
centers = flspp.cluster_centers_
|
|
70
|
+
|
|
71
|
+
print(labels) # [1, 1, 1, 0, 0, 0]
|
|
72
|
+
print(centers) # [[2.1, 2.1, 2.1], [1.1, 1.1, 1.1]]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Development
|
|
76
|
+
|
|
77
|
+
Install [poetry](https://python-poetry.org/docs/#installation)
|
|
78
|
+
```bash
|
|
79
|
+
curl -sSL https://install.python-poetry.org | python3 -
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Install clang
|
|
83
|
+
```bash
|
|
84
|
+
sudo apt-get install clang
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Set clang variables
|
|
88
|
+
```bash
|
|
89
|
+
export CXX=/usr/bin/clang++
|
|
90
|
+
export CC=/usr/bin/clang
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Install the package
|
|
94
|
+
```bash
|
|
95
|
+
poetry install
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If the installation does not work and you do not see the C++ output, you can build the package to see the stack trace
|
|
99
|
+
```bash
|
|
100
|
+
poetry build
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Run the tests
|
|
104
|
+
```bash
|
|
105
|
+
poetry run python -m unittest discover tests -v
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Citation
|
|
109
|
+
|
|
110
|
+
If you use this code, please cite the following paper:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Theo Conrads, Lukas Drexler, Joshua Könen, Daniel R. Schmidt and Melanie Schmidt. "Local Search k-means++ with Foresight" (2024). Accepted at SEA 2024.
|
|
114
|
+
```
|
|
115
|
+
|
flspp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[](https://github.com/algo-hhu/FLSpp/actions)
|
|
2
|
+
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
[](https://www.python.org/downloads/release/python-390/)
|
|
4
|
+
[](https://pypi.org/project/flspp/)
|
|
5
|
+
|
|
6
|
+
# FLS++
|
|
7
|
+
|
|
8
|
+
An implementation of the FLS++ algorithm for k-means Clustering, as presented in [1]. This is an improvement of the LS++ algorithm presented by Lattanzi and Sohler in [2].
|
|
9
|
+
|
|
10
|
+
One can think of the algorithm as working in 3 phases:
|
|
11
|
+
|
|
12
|
+
1. Initializing centers with k-means++ (as presented in [3]).
|
|
13
|
+
2. Improving the center set by performing local search swaps (for details, see [1]).
|
|
14
|
+
3. Converging the solution with LLoyd's algorithm (also known as "the" k-means algorithm).
|
|
15
|
+
|
|
16
|
+
In [2] it is shown that `O(k log log k)` local search iterations yield a constant factor approximation. However, in both [1] and [2] it is shown that, in practice, a very small number of iterations (e.g. 20) already yields very good results, at very reasonable runtime.
|
|
17
|
+
|
|
18
|
+
The interface is built in the same way as scikit-learn's KMeans for better compatibility.
|
|
19
|
+
|
|
20
|
+
## References
|
|
21
|
+
|
|
22
|
+
[1] Theo Conrads, Lukas Drexler, Joshua Könen, Daniel R. Schmidt and Melanie Schmidt. "Local Search k-means++ with Foresight" (2024)
|
|
23
|
+
|
|
24
|
+
[2] Silvio Lattanzi and Christian Sohler. A better k-means++ algorithm via local search. In Proc.444
|
|
25
|
+
of the 36th ICML, volume 97 of Proceedings of Machine Learning Research, pages 3662–3671.445
|
|
26
|
+
PMLR, 09–15 Jun 2019
|
|
27
|
+
|
|
28
|
+
[3] David Arthur and Sergei Vassilvitskii. K-means++: The advantages of careful seeding. In409
|
|
29
|
+
Proceedings of the 18th SODA, page 1027–1035, USA, 2007
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install flspp
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Example
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from flspp import FLSpp
|
|
41
|
+
|
|
42
|
+
example_data = [
|
|
43
|
+
[1.0, 1.0, 1.0],
|
|
44
|
+
[1.1, 1.1, 1.1],
|
|
45
|
+
[1.2, 1.2, 1.2],
|
|
46
|
+
[2.0, 2.0, 2.0],
|
|
47
|
+
[2.1, 2.1, 2.1],
|
|
48
|
+
[2.2, 2.2, 2.2],
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
flspp = FLSpp(n_clusters=2)
|
|
52
|
+
labels = flspp.fit_predict(example_data)
|
|
53
|
+
centers = flspp.cluster_centers_
|
|
54
|
+
|
|
55
|
+
print(labels) # [1, 1, 1, 0, 0, 0]
|
|
56
|
+
print(centers) # [[2.1, 2.1, 2.1], [1.1, 1.1, 1.1]]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
Install [poetry](https://python-poetry.org/docs/#installation)
|
|
62
|
+
```bash
|
|
63
|
+
curl -sSL https://install.python-poetry.org | python3 -
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Install clang
|
|
67
|
+
```bash
|
|
68
|
+
sudo apt-get install clang
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Set clang variables
|
|
72
|
+
```bash
|
|
73
|
+
export CXX=/usr/bin/clang++
|
|
74
|
+
export CC=/usr/bin/clang
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Install the package
|
|
78
|
+
```bash
|
|
79
|
+
poetry install
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If the installation does not work and you do not see the C++ output, you can build the package to see the stack trace
|
|
83
|
+
```bash
|
|
84
|
+
poetry build
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run the tests
|
|
88
|
+
```bash
|
|
89
|
+
poetry run python -m unittest discover tests -v
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Citation
|
|
93
|
+
|
|
94
|
+
If you use this code, please cite the following paper:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Theo Conrads, Lukas Drexler, Joshua Könen, Daniel R. Schmidt and Melanie Schmidt. "Local Search k-means++ with Foresight" (2024). Accepted at SEA 2024.
|
|
98
|
+
```
|
flspp-0.1.0/build.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from setuptools import Extension
|
|
4
|
+
from setuptools.command.build_ext import build_ext
|
|
5
|
+
from setuptools.errors import CompileError
|
|
6
|
+
|
|
7
|
+
extension = Extension(
|
|
8
|
+
name="flspp._core",
|
|
9
|
+
sources=[
|
|
10
|
+
"flspp/_core.cpp",
|
|
11
|
+
"flspp/clustering_algorithm.cpp",
|
|
12
|
+
"flspp/clustering.cpp",
|
|
13
|
+
"flspp/makros.cpp",
|
|
14
|
+
"flspp/random_generator.cpp",
|
|
15
|
+
],
|
|
16
|
+
include_dirs=["flspp"],
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Thank you https://github.com/dstein64/kmeans1d!
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BuildExt(build_ext):
|
|
23
|
+
"""A custom build extension for adding -stdlib arguments for clang++."""
|
|
24
|
+
|
|
25
|
+
def build_extensions(self) -> None:
|
|
26
|
+
# '-std=c++11' is added to `extra_compile_args` so the code can compile
|
|
27
|
+
# with clang++. This works across compilers (ignored by MSVC).
|
|
28
|
+
for extension in self.extensions:
|
|
29
|
+
extension.extra_compile_args.append("-std=c++11")
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
build_ext.build_extensions(self)
|
|
33
|
+
except CompileError:
|
|
34
|
+
# Workaround Issue #2.
|
|
35
|
+
# '-stdlib=libc++' is added to `extra_compile_args` and `extra_link_args`
|
|
36
|
+
# so the code can compile on macOS with Anaconda.
|
|
37
|
+
for extension in self.extensions:
|
|
38
|
+
extension.extra_compile_args.append("-stdlib=libc++")
|
|
39
|
+
extension.extra_link_args.append("-stdlib=libc++")
|
|
40
|
+
build_ext.build_extensions(self)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def build(setup_kwargs: Dict[str, Any]) -> None:
|
|
44
|
+
setup_kwargs.update(
|
|
45
|
+
{"ext_modules": [extension], "cmdclass": {"build_ext": BuildExt}}
|
|
46
|
+
)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#include <Python.h>
|
|
2
|
+
|
|
3
|
+
#include "random_generator.h"
|
|
4
|
+
#include "clustering_algorithm.h"
|
|
5
|
+
#include "additional_vector_stuff.h"
|
|
6
|
+
#include "makros.h"
|
|
7
|
+
|
|
8
|
+
std::vector<Point> array_to_vector(double **array, int rows, int columns)
|
|
9
|
+
{
|
|
10
|
+
|
|
11
|
+
std::vector<Point> points;
|
|
12
|
+
|
|
13
|
+
for (int i = 0; i < rows; ++i)
|
|
14
|
+
{
|
|
15
|
+
std::vector<double> row;
|
|
16
|
+
for (int j = 0; j < columns; ++j)
|
|
17
|
+
{
|
|
18
|
+
row.push_back(array[i][j]);
|
|
19
|
+
}
|
|
20
|
+
Point p = Point(columns, i, row);
|
|
21
|
+
points.push_back(p);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return points;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Thank you https://github.com/dstein64/kmeans1d!
|
|
28
|
+
|
|
29
|
+
extern "C"
|
|
30
|
+
{
|
|
31
|
+
// "__declspec(dllexport)" causes the function to be exported when compiling on Windows.
|
|
32
|
+
// Otherwise, the function is not exported and the code raises
|
|
33
|
+
// "AttributeError: function 'cluster' not found".
|
|
34
|
+
// Exporting is a Windows platform requirement, not just a Visual Studio requirement
|
|
35
|
+
// (https://stackoverflow.com/a/22288874/1509433). The _WIN32 macro covers the Visual
|
|
36
|
+
// Studio compiler (MSVC) and MinGW. The __CYGWIN__ macro covers gcc and clang under
|
|
37
|
+
// Cygwin.
|
|
38
|
+
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
39
|
+
__declspec(dllexport)
|
|
40
|
+
#endif
|
|
41
|
+
double
|
|
42
|
+
cluster(double **array,
|
|
43
|
+
uint n,
|
|
44
|
+
uint d,
|
|
45
|
+
uint k,
|
|
46
|
+
uint lloyd_iterations,
|
|
47
|
+
uint local_search_iterations,
|
|
48
|
+
int *labels,
|
|
49
|
+
double *centers,
|
|
50
|
+
int *iterations)
|
|
51
|
+
{
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* double** array: input points (as an array of coordinate arrays)
|
|
55
|
+
* int n: number of input points
|
|
56
|
+
* int d: dimension/number of features
|
|
57
|
+
* int k: number of centers
|
|
58
|
+
* int lloyd_iterations: how many iterations of lloyd's algorithm are performed (choose -1 for precision-based termination)
|
|
59
|
+
* int local_search_iterations: how many local search steps /center swaps are performed
|
|
60
|
+
* int* cluster: array of length n, which will eventually contain the labels for each point (i.e. cluster membership)
|
|
61
|
+
* double** centers: (k x d)-array, which will eventually contain coordinates of final centers
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
// transform input array to vector of "Points" (to be able to use existing constructor for FLSPP object)
|
|
65
|
+
std::vector<Point> points = array_to_vector(array, n, d);
|
|
66
|
+
|
|
67
|
+
// create FLSPP object from vector of points
|
|
68
|
+
FLSPP my_flspp(points);
|
|
69
|
+
|
|
70
|
+
// output_algorithm object contains information such as final labels and final centers
|
|
71
|
+
output_algorithm flspp_output = my_flspp.algorithm(k);
|
|
72
|
+
|
|
73
|
+
memcpy(labels, flspp_output.final_labels.data(), n * sizeof(int));
|
|
74
|
+
|
|
75
|
+
// flspp_output has vector<Point> attribute final_centers, containing the final centers as instances of class Point
|
|
76
|
+
for (int j = 0; j < k; ++j)
|
|
77
|
+
{
|
|
78
|
+
// get coordinates of j-th center
|
|
79
|
+
std::vector<double> center_coordinates = flspp_output.final_centers[j].coordinates;
|
|
80
|
+
// We save it in a continuous array
|
|
81
|
+
for (int l = 0; l < d; ++l)
|
|
82
|
+
{
|
|
83
|
+
centers[j * d + l] = center_coordinates[l];
|
|
84
|
+
// std::cout << centers[j][l] << " ";
|
|
85
|
+
}
|
|
86
|
+
// std::cout << std::endl;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
*iterations = flspp_output.iterations;
|
|
90
|
+
|
|
91
|
+
return flspp_output.cost;
|
|
92
|
+
}
|
|
93
|
+
} // extern "C"
|
|
94
|
+
|
|
95
|
+
static PyMethodDef module_methods[] = {
|
|
96
|
+
{NULL, NULL, 0, NULL}};
|
|
97
|
+
|
|
98
|
+
static struct PyModuleDef _coremodule = {
|
|
99
|
+
PyModuleDef_HEAD_INIT,
|
|
100
|
+
"flspp._core",
|
|
101
|
+
NULL,
|
|
102
|
+
-1,
|
|
103
|
+
module_methods,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
PyMODINIT_FUNC PyInit__core(void)
|
|
107
|
+
{
|
|
108
|
+
return PyModule_Create(&_coremodule);
|
|
109
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <vector>
|
|
3
|
+
#include <iterator>
|
|
4
|
+
#include "clustering.h"
|
|
5
|
+
#include "makros.h"
|
|
6
|
+
|
|
7
|
+
// overload comparison of vectors
|
|
8
|
+
// template<typename T>
|
|
9
|
+
// bool operator==(const std::vector<T>& lhs, const std::vector<T>& rhs);
|
|
10
|
+
|
|
11
|
+
// templates can not be compiled => They can not be included in a cpp file
|
|
12
|
+
// https://stackoverflow.com/questions/1639797/template-issue-causes-linker-error-c
|
|
13
|
+
|
|
14
|
+
template <typename T>
|
|
15
|
+
inline bool operator==(const std::vector<T> &lhs, const std::vector<T> &rhs)
|
|
16
|
+
{
|
|
17
|
+
if (lhs.size() != rhs.size())
|
|
18
|
+
return false;
|
|
19
|
+
for (int i = 0; i < lhs.size(); i++)
|
|
20
|
+
{
|
|
21
|
+
if (lhs[i] != rhs[i])
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
template <typename T>
|
|
28
|
+
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec)
|
|
29
|
+
{
|
|
30
|
+
for (auto elem : vec)
|
|
31
|
+
{
|
|
32
|
+
os << elem << " ";
|
|
33
|
+
}
|
|
34
|
+
return os;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// printing vectors
|
|
38
|
+
// template <typename T>
|
|
39
|
+
// std::ostream& operator << (std::ostream& os, const std::vector<T>& vec);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by lukas on 01.12.22.
|
|
3
|
+
// Implementation of classes defined in clustering.h
|
|
4
|
+
|
|
5
|
+
#include "clustering.h"
|
|
6
|
+
|
|
7
|
+
Point::Point(int dim, int ind, std::vector<double> coord) : dimension(dim), index(ind), coordinates(coord)
|
|
8
|
+
{
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Point::Point(Point const &p) : dimension(p.dimension), index(p.index), coordinates(p.coordinates)
|
|
12
|
+
{
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Point::Point()
|
|
16
|
+
{
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
bool operator==(const Point &lhs, const Point &rhs)
|
|
20
|
+
{
|
|
21
|
+
// we only compare the coordinates, since some of the other values may not be initialized
|
|
22
|
+
return lhs.coordinates == rhs.coordinates;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
bool operator!=(const Point &lhs, const Point &rhs)
|
|
26
|
+
{
|
|
27
|
+
return !(lhs == rhs);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
std::ostream &operator<<(std::ostream &os, const Point &p)
|
|
31
|
+
{
|
|
32
|
+
os << "[ " << p.coordinates << "]";
|
|
33
|
+
|
|
34
|
+
return os;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void Point::operator+=(const Point &other)
|
|
38
|
+
{
|
|
39
|
+
if (coordinates.size() != other.coordinates.size())
|
|
40
|
+
{
|
|
41
|
+
throw std::invalid_argument("Points must have the same number of dimensions.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for (size_t i = 0; i < coordinates.size(); ++i)
|
|
45
|
+
{
|
|
46
|
+
coordinates[i] += other.coordinates[i];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
double euclidean_distance_squared(Point &x, Point &y)
|
|
51
|
+
{
|
|
52
|
+
double distance = 0;
|
|
53
|
+
double a, b;
|
|
54
|
+
for (int i = 0; i < x.dimension; ++i)
|
|
55
|
+
{
|
|
56
|
+
// distance += (x.coordinates[i] - y.coordinates[i]) * (x.coordinates[i] - y.coordinates[i]);
|
|
57
|
+
// distance += std::pow(x.coordinates[i] - y.coordinates[i],2);
|
|
58
|
+
a = x.coordinates[i];
|
|
59
|
+
b = y.coordinates[i];
|
|
60
|
+
distance += (a - b) * (a - b);
|
|
61
|
+
}
|
|
62
|
+
return distance;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Cluster::Cluster(int ind, Point centr) : index(ind), centroid(centr) {}
|
|
66
|
+
|
|
67
|
+
void Cluster::add_member(Point p)
|
|
68
|
+
{
|
|
69
|
+
members.push_back(p);
|
|
70
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by lukas on 21.11.22.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// #ifndef FLS___CLUSTERING_H
|
|
6
|
+
// #define FLS___CLUSTERING_H
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include <iterator>
|
|
11
|
+
#include <iostream>
|
|
12
|
+
#include <cmath>
|
|
13
|
+
|
|
14
|
+
#include "additional_vector_stuff.h"
|
|
15
|
+
#include "makros.h"
|
|
16
|
+
|
|
17
|
+
// MAYBE TWO DISTINCT CLASSES: ONE FOR "NORMAL" POINTS, ONE FOR CENTERS?
|
|
18
|
+
class Point
|
|
19
|
+
{
|
|
20
|
+
public:
|
|
21
|
+
int dimension;
|
|
22
|
+
int index;
|
|
23
|
+
|
|
24
|
+
std::vector<double> coordinates;
|
|
25
|
+
|
|
26
|
+
Point(int dim, int ind, std::vector<double> coord);
|
|
27
|
+
Point(Point const &p);
|
|
28
|
+
Point();
|
|
29
|
+
|
|
30
|
+
void operator+=(const Point &other);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
bool operator==(const Point &lhs, const Point &rhs);
|
|
34
|
+
bool operator!=(const Point &lhs, const Point &rhs);
|
|
35
|
+
|
|
36
|
+
// Overload the += operator to add another Point to this Point
|
|
37
|
+
|
|
38
|
+
std::ostream &operator<<(std::ostream &os, const Point &p);
|
|
39
|
+
|
|
40
|
+
double euclidean_distance_squared(Point &x, Point &y);
|
|
41
|
+
|
|
42
|
+
class Cluster
|
|
43
|
+
{
|
|
44
|
+
public:
|
|
45
|
+
int index;
|
|
46
|
+
Point centroid;
|
|
47
|
+
|
|
48
|
+
Cluster(int ind, Point centr);
|
|
49
|
+
|
|
50
|
+
void add_member(Point p);
|
|
51
|
+
|
|
52
|
+
private:
|
|
53
|
+
std::vector<Point> members;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// #endif //FLS___CLUSTERING_H
|