Orthonormal basis (Gram-Schmidt)
Background
Gram-Schmidt turns any set of vectors into an orthonormal basis for the space they span — a set of mutually perpendicular unit vectors. Orthonormal bases make projections, least-squares, and QR factorization simple, and they underpin numerical stability throughout linear algebra.
Problem statement
Implement orthonormal_basis(vectors, tol) using the Gram-Schmidt process. Process the input vectors in order; for each , subtract its projection onto every basis vector already collected, then normalise and keep it only if its remaining norm exceeds tol:
Input
vectors—list[list[float]]: the input vectors (all the same dimension).tol—float(default1e-10): a vector whose residual norm falls below this is treated as linearly dependent and dropped.
Output
Returns a list[np.ndarray]: an orthonormal basis for the span of the inputs (its length equals the rank).
Examples
Example 1
Input: orthonormal_basis([[1, 0], [1, 1]])
Output: [array([1., 0.]), array([0., 1.])]
Explanation: normalises to itself; for , subtract its projection onto the first basis vector, leaving , which normalises to .
Constraints
- Subtract projections onto all previously accepted basis vectors before normalising (classical Gram-Schmidt).
- Drop any vector whose residual norm is
tol(linearly dependent). - The returned vectors are mutually orthogonal and of unit length.
Notes
- The number of returned vectors equals the rank of the input set; dependent vectors collapse to near-zero residuals and are skipped.
- Classical Gram-Schmidt can lose orthogonality under floating-point error for ill-conditioned inputs; the modified Gram-Schmidt variant is more numerically stable.
This problem ships 4 hidden tests. They run in your browser via Pyodide — no backend, no submission queue. Press ▶ Run tests to execute.
- •Reference example -> standard basis
- •Basis vectors are orthonormal
- •Linearly dependent vectors are dropped (count == rank)
- •Each returned vector has unit norm