Skip to content

Commit 9f35da2

Browse files
authored
[Internals] Back to TaylorSeries.jl (#313)
1 parent 0afbb1e commit 9f35da2

32 files changed

+280
-149
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2424
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
2525
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
2626
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
27-
WilliamsonTransforms = "48feb556-9bdd-43a2-8e10-96100ec25e22"
27+
TaylorSeries = "6aa5eb33-94cf-58f4-a9d0-e4b2c4fc25ea"
2828

2929
[weakdeps]
3030
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
@@ -59,9 +59,9 @@ StableRNGs = "1"
5959
Statistics = "1"
6060
StatsBase = "0.33, 0.34"
6161
StatsFuns = "0.9, 1.3"
62+
TaylorSeries = "0.20"
6263
Test = "1"
6364
TestItemRunner = "1"
64-
WilliamsonTransforms = "0.2"
6565
julia = "1"
6666

6767
[extras]

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
<a href="https://github.com/lrnv/Copulas.jl/actions/workflows/CI.yml?query=branch%3Amain"><img src="https://github.com/lrnv/Copulas.jl/actions/workflows/CI.yml/badge.svg?branch=main" alt="Build Status" /></a>
1212
<a href="https://codecov.io/gh/lrnv/Copulas.jl"><img src="https://codecov.io/gh/lrnv/Copulas.jl/branch/main/graph/badge.svg"/></a>
1313
<a href="https://github.com/JuliaTesting/Aqua.jl"><img src="https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg" alt="Aqua QA" /></a>
14-
<!-- <a href="https://benchmark.tansongchen.com/TaylorDiff.jl"><img src="https://img.shields.io/buildkite/2c801728055463e7c8baeeb3cc187b964587235a49b3ed39ab/main.svg?label=benchmark" alt="Benchmark Status" /></a> -->
1514
<br />
1615
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT" /></a>
1716
<a href="https://github.com/SciML/ColPrac"><img src="https://img.shields.io/badge/contributor's%20guide-ColPrac-blueviolet" alt="ColPrac: Contributor's Guide on Collaborative Practices for Community Packages" /></a>

docs/src/bestiary/archimedean.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ In this package, we implemented it through the [`WilliamsonGenerator`](@ref) cla
9696

9797
`WilliamsonGenerator(X::UnivariateRandomVariable, d)`.
9898

99-
This function computes the Williamson d-transform of the provided random variable $X$ using the [`WilliamsonTransforms.jl`](https://github.com/lrnv/WilliamsonTransforms.jl) package. See [williamson1955multiply, mcneil2009](@cite) for the literature.
99+
This function computes the Williamson d-transform of the provided random variable $X$. See [williamson1955multiply, mcneil2009](@cite) for the literature.
100100

101101
!!! info "`max_monotony` of Williamson generators"
102102
The $d$-transform of a positive random variable is $d$-monotone but not $k$-monotone for any $k > d$. Its max monotony is therefore $d$. This has a few implications, one of the biggest is that the $d$-variate Archimedean copula that corresponds has no density.
@@ -115,15 +115,15 @@ The Williamson d-transform is a bijective transformation[^1] from the set of pos
115115

116116
This bijection is to be taken carefuly: the bijection is between random variables *with unit scales* and generators *with common value at 1*, sicne on both rescaling does not change the underlying copula.
117117

118-
This transformation is implemented through one method in the Generator interface that is worth talking a bit about : `williamson_dist(G::Generator, d)`. This function computes the inverse Williamson d-transform of the d-monotone archimedean generator ϕ, still using the [`WilliamsonTransforms.jl`](https://github.com/lrnv/WilliamsonTransforms.jl) package. See [williamson1955multiply, mcneil2009](@cite).
118+
This transformation is implemented through one method in the Generator interface that is worth talking a bit about : `williamson_dist(G::Generator, d)`. This function computes the inverse Williamson d-transform of the d-monotone archimedean generator ϕ. See [williamson1955multiply, mcneil2009](@cite).
119119

120120
To put it in a nutshell, for ``\phi`` a ``d``-monotone archimedean generator, the inverse Williamson-d-transform of ``\\phi`` is the cumulative distribution function ``F`` of a non-negative random variable ``R``, defined by :
121121

122122
```math
123123
F(x) = 𝒲_{d}^{-1}(\phi)(x) = 1 - \frac{(-x)^{d-1} \phi_+^{(d-1)}(x)}{k!} - \sum_{k=0}^{d-2} \frac{(-x)^k \phi^{(k)}(x)}{k!}
124124
```
125125

126-
The [`WilliamsonTransforms.jl`](https://github.com/lrnv/WilliamsonTransforms.jl) package implements this transformation (and its inverse, the Williamson d-transfrom) in all generality. It returns this cumulative distribution function in the form of the corresponding random variable `<:Distributions.ContinuousUnivariateDistribution` from `Distributions.jl`. You may then compute :
126+
It returns this cumulative distribution function in the form of the corresponding random variable `<:Distributions.ContinuousUnivariateDistribution` from `Distributions.jl`. You may then compute :
127127
* The cdf via `Distributions.cdf`
128128
* The pdf via `Distributions.pdf` and the logpdf via `Distributions.logpdf`
129129
* Samples from the distribution via `rand(X,n)`.
@@ -184,14 +184,14 @@ This is why `williamson_dist(G::Generator,d)` is such an important function in t
184184

185185
```@example
186186
using Copulas: williamson_dist, FrankGenerator
187-
williamson_dist(FrankGenerator(7), Val{3}())
187+
williamson_dist(FrankGenerator(7), 3)
188188
```
189189

190190
For the Frank Copula, as for many classic copulas, the distribution used is known. We pull some of them from `Distributions.jl` but implement a few more, as this Logarithmic one. Another useful example are negatively-dependent Clayton copulas:
191191

192192
```@example
193193
using Copulas: williamson_dist, ClaytonGenerator
194-
williamson_dist(ClaytonGenerator(-0.2), Val{3}())
194+
williamson_dist(ClaytonGenerator(-0.2), 3)
195195
```
196196

197197
for which the corresponding distribution is known but has no particular name, thus we implemented it under the `ClaytonWilliamsonDistribution` name.
@@ -209,7 +209,7 @@ for which the corresponding distribution is known but has no particular name, th
209209
We use this fraily approach for several generators, since sometimes it is faster, including e.g. the Clayton one with positive dependence:
210210
```@example
211211
using Copulas: williamson_dist, ClaytonGenerator
212-
williamson_dist(ClaytonGenerator(10), Val{3}())
212+
williamson_dist(ClaytonGenerator(10), 3)
213213
```
214214

215215

docs/src/bestiary/empirical.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ Usage:
216216

217217
- Build from data `u::d×n` (raw or pseudos): `Ĝ = EmpiricalGenerator(u; pseudo_values=true)`
218218
- Use directly in an Archimedean copula: `Ĉ = ArchimedeanCopula(d, Ĝ)`
219-
- Access the fitted radial law: `R̂ = williamson_dist(Ĝ, Val{d}())`
219+
- Access the fitted radial law: `R̂ = williamson_dist(Ĝ, d)`
220220

221221
```@docs; canonical=false
222222
EmpiricalGenerator

docs/src/examples/archimedean_radial_estimation.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ R = Dirac(1.0)
205205
d, n = 3, 1000
206206
u = spl_cop(R, d, n)
207207
Ghat = EmpiricalGenerator(u)
208-
Rhat = Copulas.williamson_dist(Ghat, Val{d}())
208+
Rhat = Copulas.williamson_dist(Ghat, d)
209209
diagnose_plots(u, Rhat; R=R)
210210
```
211211

@@ -216,7 +216,7 @@ R = DiscreteNonParametric([1.0, 4.0, 8.0], fill(1/3, 3))
216216
d, n = 2, 1000
217217
u = spl_cop(R, d, n)
218218
Ghat = EmpiricalGenerator(u)
219-
Rhat = Copulas.williamson_dist(Ghat, Val{d}())
219+
Rhat = Copulas.williamson_dist(Ghat, d)
220220
diagnose_plots(u, Rhat; R=R)
221221
```
222222

@@ -227,7 +227,7 @@ R = DiscreteNonParametric([1.0, 4.0, 8.0], fill(1/3, 3))
227227
d, n = 3, 1000
228228
u = spl_cop(R, d, n)
229229
Ghat = EmpiricalGenerator(u)
230-
Rhat = Copulas.williamson_dist(Ghat, Val{d}())
230+
Rhat = Copulas.williamson_dist(Ghat, d)
231231
diagnose_plots(u, Rhat; R=R)
232232
```
233233

@@ -238,7 +238,7 @@ R = LogNormal(1, 3)
238238
d, n = 10, 1000
239239
u = spl_cop(R, d, n)
240240
Ghat = EmpiricalGenerator(u)
241-
Rhat = Copulas.williamson_dist(Ghat, Val{d}())
241+
Rhat = Copulas.williamson_dist(Ghat, d)
242242
diagnose_plots(u, Rhat; R=R, logged=true)
243243
```
244244

@@ -249,7 +249,7 @@ R = Pareto(1.0, 1/2)
249249
d, n = 10, 1000
250250
u = spl_cop(R, d, n)
251251
Ghat = EmpiricalGenerator(u)
252-
Rhat = Copulas.williamson_dist(Ghat, Val{d}())
252+
Rhat = Copulas.williamson_dist(Ghat, d)
253253
diagnose_plots(u, Rhat; R=R, logged=true)
254254
```
255255

src/ArchimaxCopula.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ function Distributions._logpdf(C::ArchimaxCopula{2, TG, TT}, u) where {TG, TT}
201201

202202
s = S * A0
203203
φp = ϕ⁽¹⁾(C.gen, s) # < 0
204-
φpp = ϕ⁽ᵏ⁾(C.gen, Val(2), s) # > 0
204+
φpp = ϕ⁽ᵏ⁾(C.gen, 2, s) # > 0
205205

206206
base = su*sv + (φp/φpp)*suv
207207
base > 0 || return T(-Inf)

src/ArchimedeanCopula.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ function Distributions._logpdf(C::ArchimedeanCopula{d,TG}, u) where {d,TG}
6565
if !all(0 .< u .< 1)
6666
return eltype(u)(-Inf)
6767
end
68-
return log(max(ϕ⁽ᵏ⁾(C.G, Val{d}(), sum(ϕ⁻¹.(C.G, u))) * prod(ϕ⁻¹⁽¹⁾.(C.G, u)), 0))
68+
return log(max(ϕ⁽ᵏ⁾(C.G, d, sum(ϕ⁻¹.(C.G, u))) * prod(ϕ⁻¹⁽¹⁾.(C.G, u)), 0))
6969
end
7070
function Distributions._rand!(rng::Distributions.AbstractRNG, C::ArchimedeanCopula{d, TG}, x::AbstractVector{T}) where {T<:Real, d, TG}
7171
# By default, we use the Williamson sampling.
7272
Random.randexp!(rng,x)
73-
r = rand(rng, williamson_dist(C.G, Val{d}()))
73+
r = rand(rng, williamson_dist(C.G, d))
7474
sx = sum(x)
7575
for i in 1:length(C)
7676
x[i] = ϕ(C.G,r * x[i]/sx)
@@ -135,7 +135,7 @@ function rosenblatt(C::ArchimedeanCopula{d,TG}, u::AbstractMatrix{<:Real}) where
135135
if iszero(rⱼ)
136136
U[j,i] = zero(rⱼ)
137137
else
138-
A, B = ϕ⁽ᵏ⁾(C.G, Val(j - 1), rⱼ), ϕ⁽ᵏ⁾(C.G, Val(j - 1), rⱼ₋₁)
138+
A, B = ϕ⁽ᵏ⁾(C.G, j - 1, rⱼ), ϕ⁽ᵏ⁾(C.G, j - 1, rⱼ₋₁)
139139
U[j,i] = A / B
140140
end
141141
end
@@ -155,8 +155,8 @@ function inverse_rosenblatt(C::ArchimedeanCopula{d,TG}, u::AbstractMatrix{<:Real
155155
elseif !isfinite(Cᵢⱼ)
156156
U[j,i] = zero(Cᵢⱼ)
157157
else
158-
Dᵢⱼ = ϕ⁽ᵏ⁾(C.G, Val{j - 1}(), Cᵢⱼ) * u[j,i]
159-
R = ϕ⁽ᵏ⁾⁻¹(C.G, Val{j - 1}(), Dᵢⱼ; start_at=Cᵢⱼ)
158+
Dᵢⱼ = ϕ⁽ᵏ⁾(C.G, j - 1, Cᵢⱼ) * u[j,i]
159+
R = ϕ⁽ᵏ⁾⁻¹(C.G, j - 1, Dᵢⱼ; start_at=Cᵢⱼ)
160160
U[j, i] = ϕ(C.G, R - Cᵢⱼ)
161161
Cᵢⱼ = R
162162
end
@@ -172,10 +172,10 @@ function DistortionFromCop(C::ArchimedeanCopula, js::NTuple{p,Int}, uⱼₛ::NTu
172172
@inbounds for u in uⱼₛ
173173
sJ += ϕ⁻¹(C.G, u)
174174
end
175-
return ArchimedeanDistortion(C.G, p, float(sJ), float(T(ϕ⁽ᵏ⁾(C.G, Val{p}(), sJ))))
175+
return ArchimedeanDistortion(C.G, p, float(sJ), float(T(ϕ⁽ᵏ⁾(C.G, p, sJ))))
176176
end
177177
function ConditionalCopula(C::ArchimedeanCopula{D}, ::NTuple{p,Int}, uⱼₛ::NTuple{p,Float64}) where {D, p}
178-
return ArchimedeanCopula(D - p, TiltedGenerator(C.G, Val{p}(), sum(ϕ⁻¹.(C.G, uⱼₛ))))
178+
return ArchimedeanCopula(D - p, TiltedGenerator(C.G, p, sum(ϕ⁻¹.(C.G, uⱼₛ))))
179179
end
180180
SubsetCopula(C::ArchimedeanCopula{d,TG}, dims::NTuple{p, Int}) where {d,TG,p} = ArchimedeanCopula(length(dims), C.G)
181181

src/Copulas.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ module Copulas
1212
import ForwardDiff
1313
import HCubature
1414
import MvNormalCDF
15-
import WilliamsonTransforms
1615
import Combinatorics
1716
import LogExpFunctions
1817
import QuadGK
@@ -22,6 +21,7 @@ module Copulas
2221
import LambertW
2322
import Optim
2423
import Printf
24+
import TaylorSeries
2525

2626
# Main code
2727
include("utils.jl")
@@ -82,6 +82,7 @@ module Copulas
8282
include("EllipticalCopulas/TCopula.jl")
8383

8484
# Archimedean copulas
85+
include("WilliamsonTransforms.jl")
8586
include("Generator.jl")
8687
include("ArchimedeanCopula.jl")
8788

0 commit comments

Comments
 (0)