Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions crates/aether-core/src/ml/clustering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,18 @@ impl<const D: usize> KMeans<D> {

/// Automatically determine optimal K using topological analysis
pub fn auto_k_selection<const D: usize>(data: &[[f64; D]], n: usize, epsilon: f64) -> usize {
let n = n.min(MAX_POINTS);

// Handle invalid epsilon
if !(epsilon > 0.0) {
return n.clamp(1, MAX_POINTS);
}

let eps_sq = epsilon * epsilon;

// Build epsilon-neighborhood graph and count connected components (Ξ²β‚€)
let mut components = 0;
let mut visited = [false; MAX_POINTS];
let n = n.min(MAX_POINTS);

for start in 0..n {
if visited[start] {
Expand All @@ -300,8 +308,19 @@ pub fn auto_k_selection<const D: usize>(data: &[[f64; D]], n: usize, epsilon: f6
// Add neighbors
for i in 0..n {
if !visited[i] && i != current {
let dist = distance(&data[current], &data[i]);
if dist < epsilon && top < 64 {
let mut sum = 0.0;
let mut is_neighbor = true;
for d in 0..D {
let diff = data[current][d] - data[i][d];
sum += diff * diff;
// Early exit using NaN-safe comparison
if !(sum < eps_sq) {
is_neighbor = false;
break;
}
}

if is_neighbor && top < 64 {
stack[top] = i;
top += 1;
}
Expand Down Expand Up @@ -448,8 +467,27 @@ impl<const D: usize> DBSCAN<D> {
) -> heapless::Vec<usize, MAX_POINTS> {
let mut neighbors = heapless::Vec::new();

// Handle invalid epsilon
if !(self.epsilon >= 0.0) {
return neighbors;
}

let eps_sq = self.epsilon * self.epsilon;

for j in 0..n {
if distance(&data[i], &data[j]) <= self.epsilon {
let mut sum = 0.0;
let mut is_neighbor = true;
for d in 0..D {
let diff = data[i][d] - data[j][d];
sum += diff * diff;
// Early exit using NaN-safe comparison
if !(sum <= eps_sq) {
is_neighbor = false;
break;
}
}

if is_neighbor {
let _ = neighbors.push(j);
}
}
Expand Down