/
nik2703
/
boundary_approx
Обзор
Документация
Войти
/
nik2703
/
boundary_approx
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
boundary_detector.cpp
118 строк
5 KB
nik2703
upload files
08 окт 2025, 19:39
08 окт 2025, 19:39
ccf6b5d
Код
Авторство
О чём код?
// boundary_detector.cpp #include "boundary_detector.h" #include <faiss/IndexFlat.h> #include <faiss/gpu/GpuIndexFlat.h> #include <faiss/gpu/StandardGpuResources.h> #include <iostream> #include <set> #include <vector> #include <memory> // Для std::make_unique // Вспомогательная функция: идентификация граничных точек static std::vector<BoundarySegmentTask> findBoundaryPoints( const std::vector<DataPoint>& data_points, const std::vector<int>& cluster_ids, const std::vector<faiss::idx_t>& indices, int k, int threshold ) { size_t num_points = data_points.size(); std::set<int> unique_clusters(cluster_ids.begin(), cluster_ids.end()); std::vector<BoundarySegmentTask> all_tasks; for (auto it_i = unique_clusters.begin(); it_i != unique_clusters.end(); ++it_i) { for (auto it_j = std::next(it_i); it_j != unique_clusters.end(); ++it_j) { int cluster_i = *it_i; int cluster_j = *it_j; BoundarySegmentTask task; task.cluster_i = cluster_i; task.cluster_j = cluster_j; for (size_t point_idx = 0; point_idx < num_points; ++point_idx) { if (cluster_ids[point_idx] != cluster_i && cluster_ids[point_idx] != cluster_j) { continue; } int count_neighbors_from_other_cluster = 0; // k+1 потому что включаем саму точку (индекс 0) for (int n = 0; n <= k; ++n) { faiss::idx_t neighbor_idx = indices[point_idx * (k + 1) + n]; if (neighbor_idx == static_cast<faiss::idx_t>(point_idx)) { continue; } if ((cluster_ids[point_idx] == cluster_i && cluster_ids[neighbor_idx] == cluster_j) || (cluster_ids[point_idx] == cluster_j && cluster_ids[neighbor_idx] == cluster_i)) { count_neighbors_from_other_cluster++; } } if (count_neighbors_from_other_cluster >= threshold) { task.boundary_points.push_back(data_points[point_idx]); } } if (!task.boundary_points.empty()) { all_tasks.push_back(std::move(task)); } } } return all_tasks; } BoundaryDetector::BoundaryDetector(Mode mode, int gpu_id) : mode_(mode), gpu_id_(gpu_id), gpu_res_(nullptr) { if (mode_ == Mode::GPU) { gpu_res_ = std::make_unique<faiss::gpu::StandardGpuResources>(); } } BoundaryDetector::~BoundaryDetector() = default; std::vector<BoundarySegmentTask> BoundaryDetector::detectAllBoundaries( const std::vector<DataPoint>& data_points, int k, int threshold ) { if (data_points.empty()) return {}; size_t num_points = data_points.size(); size_t dim = data_points[0].coords.size(); // Подготовка данных std::vector<float> dataset_flat(num_points * dim); std::vector<int> cluster_ids(num_points); for (size_t i = 0; i < num_points; ++i) { for (size_t d = 0; d < dim; ++d) { dataset_flat[i * dim + d] = data_points[i].coords[d]; } cluster_ids[i] = data_points[i].cluster_id; } // Выделение памяти для результатов std::vector<faiss::idx_t> indices(num_points * (k + 1)); std::vector<float> distances(num_points * (k + 1)); // <-- Обязательно! if (mode_ == Mode::CPU) { faiss::IndexFlatL2 cpu_index(dim); cpu_index.add(num_points, dataset_flat.data()); cpu_index.search(num_points, dataset_flat.data(), k + 1, distances.data(), indices.data()); } else { faiss::gpu::GpuIndexFlatConfig config; config.device = gpu_id_; faiss::gpu::GpuIndexFlatL2 gpu_index(gpu_res_.get(), dim, config); gpu_index.add(num_points, dataset_flat.data()); gpu_index.search(num_points, dataset_flat.data(), k + 1, distances.data(), indices.data()); } auto tasks = findBoundaryPoints(data_points, cluster_ids, indices, k, threshold); for (const auto& task : tasks) { std::cout << "Найдено " << task.boundary_points.size() << " граничных точек между кластерами " << task.cluster_i << " и " << task.cluster_j << " (" << (mode_ == Mode::CPU ? "CPU" : "GPU") << ").\n"; } return tasks; }