Skip to content

Conversation

JJNewkirk
Copy link

  • [Wikipedia](https://en.wikipedia.org/wiki/Kumaraswamy_distribution
  • The exponentiated Kumaraswamy Distribution and its log-transform: Lemonte et al https://www.jstor.org/stable/43601233
    I believe my functions are accurate; however in testing the mean of the current kumaraswamy.jl the did not match in some cases. I believe this to be an error in the kumaraswamy.jl in the version I was using. The EK distribution has the Kumaraswamy as a special case, so it is easy to test keeping gamma = 1.

@codecov-commenter
Copy link

codecov-commenter commented Feb 27, 2025

Codecov Report

Attention: Patch coverage is 0% with 93 lines in your changes missing coverage. Please review.

Project coverage is 85.29%. Comparing base (e470421) to head (dfb8d8a).
Report is 17 commits behind head on master.

Files with missing lines Patch % Lines
src/univariate/continuous/ekdist.jl 0.00% 93 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1951      +/-   ##
==========================================
- Coverage   86.19%   85.29%   -0.91%     
==========================================
  Files         146      147       +1     
  Lines        8768     8861      +93     
==========================================
  Hits         7558     7558              
- Misses       1210     1303      +93     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@ararslan ararslan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some preliminary suggestions and comments, haven't reviewed everything at the moment.

Comment on lines +1 to +22
"""
kumaraswamy(α,β,γ,l,u)
The exponentiated (scaled) kumaraswamy (EK) distribution is 5 paramter two of which are normalizing constants (l,u) to a range.
```
```julia
kumaraswamy() # distribution with zero log-mean and unit scale
params(d) # Get the parameters,
```
External links
* [Wikipedia](https://en.wikipedia.org/wiki/Kumaraswamy_distribution
* The exponentiated Kumaraswamy Distribution and its log-transform: Lemonte et al https://www.jstor.org/stable/43601233

"""
## NEED TO ACCOMONDATE LOG(1 -1) when x hits the upper bound of support
## I get errors in trying to extend Distiributions functions in the script because I don't understand modules lol
using Distributions
import Distributions: @check_args, @distr_support, params, convert, partype, beta, gamma
import Distributions: AbstractRNG, maximum, minimum, convert
import Distributions: pdf, logpdf, gradlogpdf, cdf, ccdf, logcdf, logccdf, quantile, cquantile, median, mean, var, skewness, kurtosis, mode
import Distributions: fit_mle


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation can be extended later to include scaling without being a breaking change, so let's keep it simpler for the time being and use the unit interval.

Also, there's no need to load those various symbols from the Distributions namespace given that this file is included within that namespace; it can already access the symbols unqualified.

The suggestion here makes the docstring content consistent with that of Kumaraswamy.

Suggested change
"""
kumaraswamy(α,β,γ,l,u)
The exponentiated (scaled) kumaraswamy (EK) distribution is 5 paramter two of which are normalizing constants (l,u) to a range.
```
```julia
kumaraswamy() # distribution with zero log-mean and unit scale
params(d) # Get the parameters,
```
External links
* [Wikipedia](https://en.wikipedia.org/wiki/Kumaraswamy_distribution
* The exponentiated Kumaraswamy Distribution and its log-transform: Lemonte et al https://www.jstor.org/stable/43601233
"""
## NEED TO ACCOMONDATE LOG(1 -1) when x hits the upper bound of support
## I get errors in trying to extend Distiributions functions in the script because I don't understand modules lol
using Distributions
import Distributions: @check_args, @distr_support, params, convert, partype, beta, gamma
import Distributions: AbstractRNG, maximum, minimum, convert
import Distributions: pdf, logpdf, gradlogpdf, cdf, ccdf, logcdf, logccdf, quantile, cquantile, median, mean, var, skewness, kurtosis, mode
import Distributions: fit_mle
"""
EKDist(α, β, γ)
The *exponentiated Kumaraswamy (EK) distribution* with shape parameters `α > 0`, `β > 0`,
and `γ > 0` has probability density function
```math
f(x; α, β, γ) = α β γ x^- 1} (x - x^α)^- 1} (1 - (1 - x^α)^β)^- 1}, \\quad 0 < x < 1
```
When `γ == 1`, this reduces to the [Kumaraswamy distribution](@ref Kumaraswamy).
References
- Lemonte, A. J., Barreto-Souza, W., & Cordeiro, G. M. (2013). The exponentiated Kumaraswamy
distribution and its log-transform. Brazilian Journal of Probability and Statistics, 27(1),
3153. http://www.jstor.org/stable/43601233
"""

Comment on lines +27 to +29
l::T
u::T
EKDist{T}(α, β, γ, l, u) where {T} = new{T}(α, β, γ, l, u)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
l::T
u::T
EKDist{T}(α, β, γ, l, u) where {T} = new{T}(α, β, γ, l, u)
EKDist{T}(α, β, γ) where {T} = new{T}(α, β, γ)

Removing the bounds as noted in the previous comment.

Comment on lines +32 to +34
function EKDist(α::T, β::T, γ::T, l::T, u::T; check_args::Bool=true) where {T <: Real}
@check_args EKDist (α, α ≥ zero(α)) (β, β ≥ zero(β)) (γ, γ ≥ zero(γ)) (l < u)
return EKDist{T}(α, β, γ, l, u)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function EKDist::T, β::T, γ::T, l::T, u::T; check_args::Bool=true) where {T <: Real}
@check_args EKDist (α, α zero(α)) (β, β zero(β)) (γ, γ zero(γ)) (l < u)
return EKDist{T}(α, β, γ, l, u)
function EKDist::T, β::T, γ::T; check_args::Bool=true) where {T<:Real}
@check_args EKDist (α, α > zero(α)) (β, β > zero(β)) (γ, γ > zero(γ))
return EKDist{T}(α, β, γ)

Lemonte et al. define the parameters to be strictly positive, not non-negative. That's noted for γ at the beginning of section 2, and for α and β immediately following equation 2.1. (That also follows from the definition of the Kumaraswamy distribution, for which the shape parameters are positive.)

Comment on lines +37 to +44
EKDist(α::Real, β::Real, γ::Real, l::Real, u::Real; check_args::Bool=true) =
EKDist(promote(α, β, γ, l, u)...; check_args=check_args)

EKDist(α::Integer, β::Integer, γ::Integer, l::Integer, u::Integer ; check_args::Bool=true) =
EKDist(float(α), float(β), float(γ), float(l), float(u); check_args=check_args)

EKDist(α::Real, β::Real, γ::Real; check_args::Bool=true) = EKDist(promote(α, β, γ, 0.0, 1.0)...; check_args=check_args)
EKDist(α::Real, β::Real; check_args::Bool=true) = EKDist(promote(α, β, 1.0, 0.0, 1.0)...; check_args=check_args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can combine this with the method for integer arguments by adding a call to float in this method, which will just be a no-op for when the arguments are already promoted to a float type.

I've also replaced here the methods that set default values with a single method that takes no arguments. This is for consistency with other distributions, e.g. Kumaraswamy. I think all arguments should be required to be supplied when any are supplied; if someone is relying on a default of γ == 1, they should just use Kumaraswamy directly instead.

Suggested change
EKDist::Real, β::Real, γ::Real, l::Real, u::Real; check_args::Bool=true) =
EKDist(promote(α, β, γ, l, u)...; check_args=check_args)
EKDist::Integer, β::Integer, γ::Integer, l::Integer, u::Integer ; check_args::Bool=true) =
EKDist(float(α), float(β), float(γ), float(l), float(u); check_args=check_args)
EKDist::Real, β::Real, γ::Real; check_args::Bool=true) = EKDist(promote(α, β, γ, 0.0, 1.0)...; check_args=check_args)
EKDist::Real, β::Real; check_args::Bool=true) = EKDist(promote(α, β, 1.0, 0.0, 1.0)...; check_args=check_args)
EKDist::Real, β::Real, γ::Real; check_args::Bool=true) =
EKDist(float.(promote(α, β, γ))...; check_args=check_args)
EKDist() = EKDist{Float64}(1.0, 1.0, 1.0)

Comment on lines +46 to +49
# @distr_support macro would set constant bounds but we need to take bounds from input
# so we will just define them ourselves
maximum(d::EKDist) = d.u
minimum(d::EKDist) = d.l
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# @distr_support macro would set constant bounds but we need to take bounds from input
# so we will just define them ourselves
maximum(d::EKDist) = d.u
minimum(d::EKDist) = d.l
@distr_support EKDist 0 1

Also note that you can use parameters as distribution support limits with this macro, see e.g. Cosine.

Comment on lines +131 to +147
function ccdf(d::EKDist, x::Real)
xs = (x - d.l) / (d.u - d.l)
α = d.α
β = d.β
γ = d.γ

return 1 - (1 - ( 1 - xs^α)^β)^γ
end

function logcdf(d::EKDist, x::Real)
return log(cdf(d, x))
end

function logccdf(d::EKDist, x::Real)
return log(ccdf(d, x))
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods aren't necessary, as they're identical to the fallback methods.

Suggested change
function ccdf(d::EKDist, x::Real)
xs = (x - d.l) / (d.u - d.l)
α = d.α
β = d.β
γ = d.γ
return 1 - (1 - ( 1 - xs^α)^β)^γ
end
function logcdf(d::EKDist, x::Real)
return log(cdf(d, x))
end
function logccdf(d::EKDist, x::Real)
return log(ccdf(d, x))
end

Comment on lines +124 to +128
xs = (x - d.l) / (d.u - d.l)
α = d.α
β = d.β
γ = d.γ
return (1 - ( 1 - xs^α)^β)^γ
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
xs = (x - d.l) / (d.u - d.l)
α = d.α
β = d.β
γ = d.γ
return (1 - ( 1 - xs^α)^β)^γ
α, β, γ = params(d)
y = (1 - (1 - clamp(x, 0, 1)^α)^β)^γ
return x < 0 ? zero(y) : (x > 1 ? one(y) : y)

Comment on lines +165 to +168
function fit_mle(::Type{<:EKDist}, x::AbstractArray{T}) where T<:Real
#incomplete
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to not define the method at all than to have it return nothing.

Suggested change
function fit_mle(::Type{<:EKDist}, x::AbstractArray{T}) where T<:Real
#incomplete
end
# `fit_mle` not yet implemented



#### Statistics
median(d::EKDist) = quantile(d, .5) # right?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is identical to the fallback definition.

Suggested change
median(d::EKDist) = quantile(d, .5) # right?

β = d.β
γ = d.γ

# can't tell from paper if its infinite sum or stops at the floor of γ -1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which part of the paper are you looking at? They looked like infinite sums to me, but maybe I missed something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants