File size: 1,020 Bytes
c30b460 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from __future__ import annotations
import numpy as np
def power_law_spectrum(d: int, exponent: float = 1.2, floor: float = 0.02) -> np.ndarray:
"""Return a descending synthetic image-like covariance spectrum."""
if d <= 0:
raise ValueError("d must be positive")
ranks = np.arange(1, d + 1, dtype=np.float64)
eig = ranks ** (-float(exponent))
eig = eig / eig[0]
return eig + float(floor)
def sample_covariance(eigenvalues: np.ndarray, n_samples: int, rng: np.random.Generator) -> np.ndarray:
eig = np.asarray(eigenvalues, dtype=np.float64)
if n_samples <= 1:
raise ValueError("n_samples must exceed one")
z = rng.standard_normal((n_samples, eig.size))
x = z * np.sqrt(eig)
x = x - x.mean(axis=0, keepdims=True)
return (x.T @ x) / float(n_samples - 1)
def symmetric_matrix_sqrt(matrix: np.ndarray) -> np.ndarray:
vals, vecs = np.linalg.eigh((matrix + matrix.T) * 0.5)
vals = np.clip(vals, 0.0, None)
return (vecs * np.sqrt(vals)) @ vecs.T
|