Linalg — symmetric eigendecomposition and graph Laplacian
linalg is pleco-xa’s small, exact linear-algebra corner: a symmetric-matrix eigensolver
and the normalized graph Laplacian. These are the two dependency-free primitives that the
Laplacian segmentation
pipeline surfaced — pure JavaScript, no native BLAS, and numerically matched to SciPy’s
output so the structural-clustering demo produces the same boundaries in Node and the
browser.
Both are fixture-gated against linalg.json: eigh reconstructs to 1e-16 with
eigenvalues within 1e-6, and laplacian matches scipy.sparse.csgraph.laplacian to 1e-9.
Key functions
Section titled “Key functions”Verified against the built barrel (linalg namespace):
eigh(input, opts)→{ values, vectors }. Symmetric eigendecomposition via cyclic Jacobi (Golub & Van Loan §8.4), matchingscipy.linalg.eigh: eigenvalues ascending, eigenvectors orthonormal.vectors[i][k]is componentiof the eigenvector forvalues[k](SciPy’s column convention).laplacian(W, opts)→Float64Array[].normed: true(default) returns the symmetric normalized LaplacianI − D^{-1/2} W D^{-1/2};normed: falsereturns the combinatorialD − W.
Example
Section titled “Example”import { linalg } from 'pleco-xa'
// A weighted adjacency matrix (symmetric):const W = [ [0, 1, 1], [1, 0, 1], [1, 1, 0],]
const L = linalg.laplacian(W, { normed: true })const { values, vectors } = linalg.eigh(L)// values are ascending; the Fiedler vector is column 1 of `vectors`const fiedler = vectors.map((row) => row[1])- Input is never shape-guessed. Pass a 2D matrix (array of rows) or a flat row-major
array with explicit
{ flat, n }. Non-square input throws. eighrequires a genuinely symmetric matrix and throws on the worst offending pair if the two triangles disagree beyond tolerance — SciPy reads only one triangle, but pleco verifies the full matrix so the returned decomposition actually reconstructs your input. Eigenvector signs are not canonicalised (the sign gauge is not part of the spectrum).laplacianfollows SciPy’s conventions exactly: the input diagonal is ignored (self-weights zeroed before the degree sum), and isolated nodes (degree 0) get a scale factor of 1, so their diagonal entry becomes0rather than1.- Jacobi throws rather than returning an unconverged result if it exceeds
maxSweeps(default 100) — raise it for ill-conditioned matrices.
API reference
Section titled “API reference”Full signatures: linalg namespace — namely
eigh and
laplacian.