Skip to content

Commit 9bd165d

Browse files
committed
Changed formula
A slightly different expression is used as it gives slightly better numerical accuracy at the extremes (q=0 and q=1).
1 parent 785540b commit 9bd165d

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

ompy/dist/fermi_dirac.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ def _ppf(self, q, lam, mu):
5353
"""
5454
Calculate the CDF for the Fermi-Dirac distribution.
5555
"""
56-
N = np.log(1 + np.exp(lam*mu))
57-
return mu - np.log(np.exp(N*(1-q)) - 1)/lam
56+
return mu - np.log((1 + np.exp(lam*mu))**(1-q) - 1)/lam
5857

5958
def _random(self, lam, mu, size=None):
6059
"""
@@ -101,6 +100,10 @@ def logp(self, value):
101100
TensorVariable
102101
"""
103102

103+
# The formula is
104+
# p(x) = lam/ln(1 + exp(lam*mu)) * 1/(exp(lam*(x-mu)) + 1)
105+
# ln(p(x)) = ln(lam/ln(1 + exp(lam*mu))) - ln(exp(lam*(x-mu)) + 1)
106+
104107
lam = self.lam
105108
mu = self.mu
106109

@@ -125,6 +128,10 @@ def logcdf(self, value):
125128
TensorVariable
126129
"""
127130

131+
# The formula is CDF
132+
# P(x) = 1 - ln(1 + exp(-lam*(x-mu)))/ln(1 + exp(lam*mu))
133+
# ln(P(x)) = ln(1 - ln(1 + exp(-lam*(x-mu)))/ln(1 + exp(lam*mu)))
134+
128135
lam = self.lam
129136
mu = self.mu
130137

ompy/dist/fermi_dirac_pymc4.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ def rng_fn(cls,
3737
mu: np.ndarray, size: Tuple[int, ...]
3838
) -> np.ndarray:
3939
q = rng.uniform(size=size)
40-
N = lam/np.log(1 + np.exp(lam*mu))
41-
return mu - np.log(1 - np.exp(lam*(1 - q)/lam))/lam
40+
return mu - np.log((1 + np.exp(lam*mu))**(1-q) - 1)/lam
4241

4342

4443
fermidirac = FermiDiracRV()
@@ -122,7 +121,6 @@ def logcdf(value, lam, mu):
122121
TensorVariable
123122
"""
124123

125-
N = lam/at.log(1 + at.exp(lam*mu))
126-
V = (at.exp(lam*(value - mu)) + 1)/(at.exp(lam*mu) + 1)
127-
logcdf = at.log(N) + at.log(lam*value - at.log(V))
124+
logcdf = at.log(1 - at.log(1 + at.exp(-lam*(value - mu))) /
125+
at.log(1 + at.exp(lam*mu)))
128126
return bound(logcdf, value >= 0, lam > 0)

tests/test_dist.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import matplotlib.pyplot as plt
88

9+
910
@pytest.mark.parametrize(
1011
"lam,mu",
1112
[(10., 1.),
@@ -29,6 +30,7 @@ def test_fermi_dirac(lam, mu):
2930
# We use a fairly large tolerance since error should be stocastic
3031
assert_allclose(hist, y, atol=0.1)
3132

33+
3234
@pytest.mark.parametrize(
3335
"lam,mu",
3436
[(10., 1.),

0 commit comments

Comments
 (0)