How to: semicircle_density
Compute the scalar density of a matrix semicircle distribution at a real point \(x\) via Stieltjes inversion.
import numpy as np
from free_matrix_laws import semicircle_density
Minimal example
n, s = 3, 2
A1 = np.eye(n)
A2 = 2*np.eye(n)
A = [A1, A2]
x = 0.0
fx = semicircle_density(x, A, eps=1e-2) # ≈ density at x
fx
Vector of points
xs = np.linspace(-6, 6, 400)
fxs = np.array([semicircle_density(x, A, eps=5e-3) for x in xs])
Signature
semicircle_density(
x: float,
A, # list/tuple of (n,n) or stacked (s,n,n)
eps: float = 1e-2,
G0=None, # optional warm start for G(z)
tol: float = 1e-10,
maxiter: int = 10_000,
) -> float
What it does
For \(z=x+i\varepsilon\) it solves $$ z\,G \;=\; I \;+\; \eta(G)\,G, \qquad \eta(B)=\sum_{i=1}^s A_i\,B\,A_i^\ast,\ \Im z>0, $$ then returns $$ f(x) \;=\; -\frac{1}{\pi}\,\Im!\left(\frac{1}{n}\,\mathrm{tr}\,G(x+i\varepsilon)\right). $$
Tips
- Imaginary part: for real \(x\), use \(z=x+i\varepsilon\) with \(\varepsilon\approx 10^{-2}\)–\(10^{-3}\).
- Warm starts: pass
G0(e.g., the solution at a nearby \(z\)) to speed up convergence. - Input shapes:
Amay be a list/tuple of \((n,n)\) arrays or a stacked array of shape \((s,n,n)\). - Numerical stability: if iterations stall, increase \(\varepsilon\), relax
tol, or raisemaxiter.
Scalar-reduction sanity check
If all \(A_i=\sigma I\), then \(G(z)=g(z)I\) and the scalar semicircle Stieltjes transform is $$ g(z)=\frac{z-\sqrt{z^{2}-4c}}{2c}, \qquad c=\sigma^{2}. $$ The density matches the semicircle on \([-2\sqrt{c},\,2\sqrt{c}]\).
See also:
biased_semicircle_density.