Остання активність 9 months ago

Definition of a Marchenko-Pastur distribution

Версія 9067d9c05fe11330ba1b2ad6bac1a54e8546e1cc

mp_distr.py Неформатований
1import numpy as np
2
3from numpy.typing import ArrayLike
4
5class MarchenkoPastur:
6 """Definition of a Marchenko-Pastur distribution"""
7
8 def __init__(self, ratio: float, sigma: float = 1.0):
9 """
10 Parameters
11 ----------
12 ratio : float
13 The ratio between the number of variables (columns) and the size of the sample (rows) contained in the data matrix.
14 For numerical stability, it should be less than 1.
15 sigma : float
16 The standard deviation of the distribution of values, by default, 1.0.
17
18 Raises
19 ------
20 ValueError
21 If ratio or sigma are not strictly positive.
22 """
23 if ratio <= 0.0:
24 raise ValueError("The ratio must be strictly positive, but found %s <= 0.0!" % ratio)
25 self.ratio = ratio
26 if sigma <= 0.0:
27 raise ValueError("The standard deviation must be strictly positive, but found %s <= 0.0!" % sigma)
28 self.sigma = sigma
29
30 # Compute the limits of the distribution
31 self.l_bottom = self.sigma**2 * (1.0 - np.sqrt(self.ratio))**2
32 self.l_upper = self.sigma**2 * (1.0 + np.sqrt(self.ratio))**2
33
34 def pdf(self, x: float | ArrayLike) -> float | ArrayLike:
35 """
36 Return the value of the probability distribution function.
37
38 Parameters
39 ----------
40 x : float | ArrayLike
41 The value(s) at which to compute the PDF.
42
43 Returns
44 -------
45 float | ArrayLike
46 The value(s) of the PDF
47 """
48 if not np.isscalar(x):
49 return np.vectorize(self.pdf, otypes=[float])(x)
50
51 if x == 0.0:
52 return 0.0
53
54 num = np.sqrt(max(self.l_upper - x, 0.0) * max(x - self.l_bottom, 0.0))
55 den = 2.0 * np.pi * self.sigma**2 * self.ratio * x
56
57 return float(num / den)