Skip to content

Commit 4bafa6c

Browse files
committed
Fixes
1 parent 4afe626 commit 4bafa6c

File tree

3 files changed

+89
-41
lines changed

3 files changed

+89
-41
lines changed
Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
LogLogistic(α, β)
33
4-
The *log logistic distribution* with scale `α` and shape `β` is the distribution of a random variable whose logarithm has a [`Logistic`](@ref) distribution.
4+
The *log-logistic distribution* with scale `α` and shape `β` is the distribution of a random variable whose logarithm has a [`Logistic`](@ref) distribution.
55
If ``X \\sim \\operatorname{LogLogistic}(\\alpha, \\beta)`` then ``log(X) \\sim \\operatorname{Logistic}(log(\\alpha), 1/\\beta)``. The probability density function is
66
77
```math
@@ -21,7 +21,6 @@ External links
2121
2222
* [Log logistic distribution on Wikipedia](https://en.wikipedia.org/wiki/Log-logistic_distribution)
2323
"""
24-
2524
struct LogLogistic{T<:Real} <: ContinuousUnivariateDistribution
2625
α::T
2726
β::T
@@ -42,70 +41,81 @@ LogLogistic() = LogLogistic(1.0, 1.0, check_args=false)
4241
#### Coversions
4342
convert(::Type{LogLogistic{T}}, d::LogLogistic{T}) where {T<:Real} = d
4443
convert(::Type{LogLogistic{T}}, d::LogLogistic) where {T<:Real} = LogLogistic{T}(T(d.α), T(d.β))
45-
#### Parameters
4644

45+
#### Parameters
4746
params(d::LogLogistic) = (d.α, d.β)
4847
partype(::LogLogistic{T}) where {T} = T
4948

5049
#### Statistics
5150

5251
median(d::LogLogistic) = d.α
53-
function mean(d::LogLogistic{T}) where T<:Real
54-
if d.β 1
55-
ArgumentError("mean is defined only when β > 1")
52+
function mean(d::LogLogistic)
53+
(; α, β) = d
54+
if !> 1)
55+
ArgumentError("the mean of a log-logistic distribution is defined only when its shape β > 1")
5656
end
57-
return d.α/sinc(1/d.β)
57+
return α/sinc(inv(β))
5858
end
5959

60-
function mode(d::LogLogistic{T}) where T<:Real
61-
if d.β 1
62-
ArgumentError("mode is defined only when β > 1")
63-
end
64-
return d.α*((d.β-1)/(d.β+1))^(1/d.β)
60+
function mode(d::LogLogistic)
61+
(; α, β) = d
62+
return α*(max- 1, 0) /+ 1))^inv(β)
6563
end
6664

67-
function var(d::LogLogistic{T}) where T<:Real
68-
if d.β 2
69-
ArgumentError("var is defined only when β > 2")
65+
function var(d::LogLogistic)
66+
(; α, β) = d
67+
if !> 2)
68+
ArgumentError("the variance of a log-logistic distribution is defined only when its shape β > 2")
7069
end
71-
b = π/d.β
72-
return d.α^2 * (2*b/sin(2*b)-b^2/(sin(b))^2)
70+
invβ = inv(β)
71+
return α^2 * (inv(sinc(2 * invβ)) - inv(sinc(invβ))^2)
7372
end
7473

74+
entropy(d::LogLogistic) = log(d.α / d.β) + 2
7575

7676
#### Evaluation
77-
function pdf(d::LogLogistic{T}, x::Real) where T<:Real
78-
# use built-in impletation to evaluate the density
79-
# of loglogistic at x
80-
# Y = log(X)
81-
# Y ~ logistic(log(θ), 1/ϕ)
82-
x >= 0 ? pdf(Logistic(log(d.α), 1/d.β), log(x)) / x : zero(T)
83-
end
8477

85-
function logpdf(d::LogLogistic{T}, x::Real) where T<:Real
86-
x >= 0 ? logpdf(Logistic(log(d.α), 1/d.β), log(x)) + log(x) : -T(Inf)
78+
function pdf(d::LogLogistic, x::Real)
79+
(; α, β) = d
80+
insupport = x > 0
81+
_x = insupport ? x : zero(x)
82+
xoαβ = (_x / α)^β
83+
res =/ x) / ((1 + xoαβ) * (1 + inv(xoαβ)))
84+
return insupport ? res : zero(res)
8785
end
88-
89-
function cdf(d::LogLogistic{T}, x::Real) where T<:Real
90-
x >= 0 ? cdf(Logistic(log(d.α), 1/d.β), log(x)) : zero(T)
86+
function logpdf(d::LogLogistic, x::Real)
87+
(; α, β) = d
88+
insupport = x > 0
89+
_x = insupport ? x : zero(x)
90+
βlogxoα = β * log(_x / α)
91+
res = log/ x) - (log1pexp(βlogxoα) + log1mexp(βlogxoα))
92+
return insupport ? res : oftype(res, -Inf)
9193
end
9294

93-
function logcdf(d::LogLogistic{T}, x::Real) where T<:Real
94-
x >= 0 ? logcdf(Logistic(log(d.α), 1/d.β), log(x)) : -T(Inf)
95-
end
95+
cdf(d::LogLogistic, x::Real) = inv(1 + (max(x, 0) / d.α)^(-d.β))
96+
ccdf(d::LogLogistic, x::Real) = inv(1 + (max(x, 0) / d.α)^d.β)
9697

97-
function ccdf(d::LogLogistic{T}, x::Real) where T<:Real
98-
x >= 0 ? ccdf(Logistic(log(d.α), 1/d.β), log(x)) : one(T)
99-
end
98+
logcdf(d::LogLogistic, x::Real) = -log1pexp(-d.β * log(max(x, 0) / d.α))
99+
logccdf(d::LogLogistic, x::Real) = -log1pexp(d.β * log(max(x, 0) / d.α))
100100

101-
function logccdf(d::LogLogistic{T}, x::Real) where T<:Real
102-
x >= 0 ? logccdf(Logistic(log(d.α), 1/d.β), log(x)) : zero(T)
103-
end
101+
quantile(d::LogLogistic, p::Real) = d.α * (p / (1 - p))^inv(d.β)
102+
cquantile(d::LogLogistic, p::Real) = d.α * ((1 - p) / p)^inv(d.β)
104103

104+
invlogcdf(d::LogLogistic, lp::Real) = d.α * expm1(-lp)^(-inv(d.β))
105+
invlogccdf(d::LogLogistic, lp::Real) = d.α * expm1(-lp)^inv(d.β)
105106

106107
#### Sampling
108+
107109
function rand(rng::AbstractRNG, d::LogLogistic)
108110
u = rand(rng)
109-
r = u / (1 - u)
110-
return r^(1/d.β)*d.α
111+
return d.α * (u / (1 - u))^(inv(d.β))
112+
end
113+
function rand!(rng::AbstractRNG, d::LogLogistic, A::AbstractArray{<:Real})
114+
rand!(rng, A)
115+
let α = d.α, invβ = inv(d.β)
116+
map!(A, A) do u
117+
return α * (u / (1 - u))^invβ
118+
end
119+
end
120+
return A
111121
end

test/ref/continuous/loglogistic.R

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
LogLogistic <- R6Class("LogLogistic",
2+
inherit = ContinuousDistribution,
3+
public = list(
4+
names = c("alpha", "beta"),
5+
alpha = NA,
6+
beta = NA,
7+
initialize = function(a=1, b=1) {
8+
self$alpha <- a
9+
self$beta <- b
10+
},
11+
supp = function() { c(0, Inf) },
12+
properties = function() {
13+
a <- self$alpha
14+
b <- self$beta
15+
g1 <- ifelse(a > 1, gamma(1 - 1/a), NaN)
16+
g2 <- ifelse(a > 2, gamma(1 - 2/a), NaN)
17+
g3 <- ifelse(a > 3, gamma(1 - 3/a), NaN)
18+
g4 <- ifelse(a > 4, gamma(1 - 4/a), NaN)
19+
gam <- 0.57721566490153286
20+
list(shape = a,
21+
scale = b,
22+
mean = ifelse(b > 1, a, NaN),
23+
median = a,
24+
mode = ifelse(b > 1, b * (a / (1 + a))^(1/a), 0.0),
25+
var = ifelse(a > 2, b^2 * (g2 - g1^2), NaN),
26+
skewness = if (a > 3) {
27+
(g3 - 3 * g2 * g1 + 2 * g1^3) / (g2 - g1^2)^1.5
28+
} else { Inf },
29+
kurtosis = if (a > 4) {
30+
(g4 - 4 * g3 * g1 + 3 * g2^2) / (g2 - g1^2)^2 - 6
31+
} else { Inf },
32+
entropy = 2 + log(a / b))
33+
},
34+
pdf = function(x, log=FALSE) { VGAM::dfisk(x, shape=self$alpha, scale=self$beta, log=log) },
35+
cdf = function(x) { VGAM::pfisk(x, shape=self$alpha, scale=self$beta) },
36+
quan = function(v) { VGAM::qfisk(v, shape=self$alpha, scale=self$beta) }
37+
)
38+
)

test/ref/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ in addition to the R language itself:
1515
| stringr | For string parsing |
1616
| R6 | OOP for implementing distributions |
1717
| extraDistr | A number of distributions |
18-
| VGAM | For ``Frechet`` and ``Levy`` |
18+
| VGAM | For ``LogLogistic``, ``Frechet`` and ``Levy`` |
1919
| distr | For ``Arcsine`` |
2020
| chi | For ``Chi`` |
2121
| circular | For ``VonMises`` |

0 commit comments

Comments
 (0)