import { ClusterBase } from '../base/cluster'; import { Params } from '../base/estimator'; /** * SpectralClustering, following sklearn.cluster.SpectralClustering. * * 1. Build the affinity matrix W: * - 'rbf': W_ij = exp(-gamma * ||x_i - x_j||^2) * - 'nearestNeighbors': k-nearest-neighbor connectivity graph (each * sample counts itself among its neighbors, as sklearn's * kneighbors_graph(include_self=True) does), symmetrized as * W = 0.5 * (A + A^T) exactly like sklearn. * 2. Form the symmetric normalized Laplacian * L_sym = I - D^{-1/2} W D^{-1/2} (degree-0 nodes are left untouched, * like scipy.sparse.csgraph.laplacian(normed=True)). * 3. Take the eigenvectors of the `nClusters` smallest eigenvalues of * L_sym. The full symmetric eigendecomposition is computed with the * cyclic Jacobi rotation method — deterministic and robust for the * (near-)degenerate zero eigenvalues that connected components produce, * where power iteration converges poorly. * 4. Row-normalize the spectral embedding (Ng, Jordan & Weiss 2001) and * cluster the rows with seeded KMeans (`nInit` restarts). * * Only assignLabels='kmeans' is supported (sklearn additionally offers * 'discretize' and 'cluster_qr'). */ export type SpectralAffinity = 'rbf' | 'nearestNeighbors'; export interface SpectralClusteringProps { /** number of clusters / dimension of the spectral embedding */ nClusters?: number; /** how to construct the affinity matrix */ affinity?: SpectralAffinity; /** kernel coefficient for the rbf affinity */ gamma?: number; /** number of neighbors for the nearestNeighbors affinity */ nNeighbors?: number; /** seed for the KMeans step */ randomState?: number; /** number of KMeans restarts on the embedding */ nInit?: number; /** label assignment strategy in the embedding space */ assignLabels?: 'kmeans'; } /** * Full eigendecomposition of a symmetric matrix by the cyclic Jacobi * rotation method. Returns eigenvalues in ascending order with the matching * eigenvectors (each a length-n array). Deterministic; handles repeated * eigenvalues (the rotations always produce an orthonormal basis). */ export declare function jacobiEigenSymmetric(A: number[][], maxSweeps?: number, tol?: number): { values: number[]; vectors: number[][]; }; export declare class SpectralClustering extends ClusterBase { private nClusters; private affinity; private gamma; private nNeighbors; private randomState?; private nInit; private assignLabels; private labels; constructor(props?: SpectralClusteringProps); getParams(): Params; fitPredict(samplesX: number[][]): number[]; getLabels(): number[]; private affinityMatrix; }