You are on page 1of 6

#include <iostream>

#include <fstream>
#include <vector>
#include <cmath>
#include <limits>

// Định nghĩa cấu trúc cho điểm dữ liệu


struct Point {
double x, y;

Point() : x(0), y(0) {}


Point(double x, double y) : x(x), y(y) {}
};

// Hàm tính khoảng cách Euclidean giữa hai điểm


double euclideanDistance(const Point& p1, const Point& p2) {
return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2));
}

// Hàm gán nhóm cho mỗi điểm dữ liệu dựa trên các trung tâm
void assignToClusters(const std::vector<Point>& data, const
std::vector<Point>& centroids, std::vector<int>& assignments) {
for (size_t i = 0; i < data.size(); ++i) {
double minDistance = std::numeric_limits<double>::max();
int clusterIndex = -1;

for (size_t j = 0; j < centroids.size(); ++j) {


double distance = euclideanDistance(data[i], centroids[j]);
if (distance < minDistance) {
minDistance = distance;
clusterIndex = j;
}
}

assignments[i] = clusterIndex;
}
}

// Hàm cập nhật trung tâm cho mỗi nhóm


void updateCentroids(const std::vector<Point>& data, const
std::vector<int>& assignments, std::vector<Point>& centroids) {
std::vector<int> clusterSizes(centroids.size(), 0);
std::vector<Point> newCentroids(centroids.size(), Point(0, 0));

for (size_t i = 0; i < data.size(); ++i) {


int clusterIndex = assignments[i];
newCentroids[clusterIndex].x += data[i].x;
newCentroids[clusterIndex].y += data[i].y;
clusterSizes[clusterIndex]++;
}

for (size_t i = 0; i < centroids.size(); ++i) {


if (clusterSizes[i] > 0) {
centroids[i].x = newCentroids[i].x / clusterSizes[i];
centroids[i].y = newCentroids[i].y / clusterSizes[i];
}
}
}

// Hàm kiểm tra xem liệu trung tâm đã thay đổi đủ chưa
bool hasConverged(const std::vector<Point>& oldCentroids, const
std::vector<Point>& newCentroids, double tolerance) {
for (size_t i = 0; i < oldCentroids.size(); ++i) {
if (euclideanDistance(oldCentroids[i], newCentroids[i]) >
tolerance) {
return false;
}
}
return true;
}

// Hàm chính triển khai thuật toán K-means


void kMeans(const std::vector<Point>& data, size_t k,
std::vector<Point>& centroids) {
// Khởi tạo trung tâm ban đầu bằng cách chọn ngẫu nhiên k điểm từ
dữ liệu
std::vector<Point> oldCentroids(centroids);
std::vector<int> assignments(data.size(), -1);

// Lặp cho đến khi trung tâm không thay đổi đủ


do {
oldCentroids = centroids;

// Gán nhóm cho mỗi điểm dữ liệu


assignToClusters(data, centroids, assignments);

// Cập nhật trung tâm


updateCentroids(data, assignments, centroids);

} while (!hasConverged(oldCentroids, centroids, 0.0001));


}
// Hàm chính triển khai thuật toán K-means và xuất thông tin
void kMeans(const std::vector<Point>& data, size_t k,
std::vector<Point>& centroids, std::vector<int>& assignments) {
// ... (như trước)

// Gán nhóm cho mỗi điểm dữ liệu


assignToClusters(data, centroids, assignments);

// In thông tin về việc mỗi đỉnh thuộc cụm nào


std::cout << "Đỉnh thuộc cụm nào:\n";
for (size_t i = 0; i < data.size(); ++i) {
std::cout << "Đỉnh " << i + 1 << " thuộc: Cụm " << assignments[i]
+ 1 << "\n";
}
}
int main() {
// Mở tệp tin tùy theo tên file
std::ifstream inputFile("test.txt");
if (!inputFile.is_open()) {
std::cerr << "Mở file ko thành công.\n";
return 1;
}

// Đọc số đỉnh và số cụm


size_t m, n;
inputFile >> m >> n;

// Đọc tọa độ mỗi đỉnh


std::vector<Point> data(m);
for (size_t i = 0; i < m; ++i) {
inputFile >> data[i].x >> data[i].y;
}

// Đọc tâm cụm ban đầu


std::vector<Point> centroids(n);
for (size_t i = 0; i < n; ++i) {
inputFile >> centroids[i].x >> centroids[i].y;
}

// Đóng tệp tin


inputFile.close();

// Áp dụng thuật toán K-means


kMeans(data, n, centroids);

// Áp dụng thuật toán K-means và lấy thông tin về phân nhóm của
mỗi đỉnh
std::vector<int> assignments(data.size(), -1);
kMeans(data, n, centroids, assignments);

// In kết quả
std::cout << "Tâm cụm sau thuật toán K-means:\n";
for (size_t i = 0; i < centroids.size(); ++i) {
std::cout << "Tâm cụm " << i + 1 << ": (" << centroids[i].x << ", "
<< centroids[i].y << ")\n";
}

return 0;
}

You might also like