import type { DataMatrix } from '../clustering/types'; export interface ClusterEvaluation { k: number; /** Silhouette score (range: [-1, 1], higher is better) */ silhouette: number; /** Davies-Bouldin index (range: [0, ∞), lower is better) */ davies_bouldin: number; /** Calinski-Harabasz index (range: [0, ∞), higher is better) */ calinski_harabasz: number; /** * Combined score used for selection. * When using the default 'combined' method, this is the mean of normalized * metrics in [0, 1]. When using 'silhouette', this is the raw silhouette. * When using 'elbow', the knee point gets score 1.0. */ combined_score: number; labels: number[]; /** Within-cluster sum of squares (inertia). Present when method is 'elbow'. */ wss?: number; } /** * Method for selecting the optimal number of clusters. * - 'combined': Normalized combination of silhouette, Calinski-Harabasz, and Davies-Bouldin * - 'elbow': WSS/inertia curve knee detection * - 'silhouette': Highest silhouette score */ export type OptimalClustersMethod = 'combined' | 'elbow' | 'silhouette'; export interface FindOptimalClustersOptions { /** Minimum number of clusters to test (default: 2) */ min_clusters?: number; /** Maximum number of clusters to test (default: 10) */ max_clusters?: number; /** Algorithm to use (default: 'kmeans') */ algorithm?: 'kmeans' | 'spectral' | 'agglomerative' | 'som'; /** * Algorithm-specific parameters forwarded to the clusterer constructor. * For `algorithm: 'agglomerative'`, `distance_threshold` is rejected because * `find_optimal_clusters` controls the stopping criterion via the k-sweep loop; * use `min_clusters`/`max_clusters` to bound the sweep instead. */ algorithm_params?: Record; /** Metrics to use for evaluation (default: all). Only used with 'combined' method. */ metrics?: Array<'silhouette' | 'davies_bouldin' | 'calinski_harabasz'>; /** * Custom scoring function. Receives raw (un-normalized) metric values. * Overrides the `method` option when provided. */ scoring_function?: (evaluation: ClusterEvaluation) => number; /** Method for selecting optimal k (default: 'combined') */ method?: OptimalClustersMethod; } /** * @example * ```typescript * import { find_optimal_clusters } from 'clustering-tfjs'; * * const data = [[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]]; * const result = await find_optimal_clusters(data, { max_clusters: 5 }); * * console.log(`Optimal number of clusters: ${result.optimal.k}`); * console.log(`Best silhouette score: ${result.optimal.silhouette}`); * ``` */ export declare function find_optimal_clusters(X: DataMatrix, options?: FindOptimalClustersOptions): Promise<{ optimal: ClusterEvaluation; evaluations: ClusterEvaluation[]; }>;