-
Notifications
You must be signed in to change notification settings - Fork 9
/
SurvivalCopula.jl
72 lines (67 loc) · 2.39 KB
/
SurvivalCopula.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""
SurvivalCopula(C,indices)
Computes the survival version of any copula on given indices. From a copula ``C`` in dimension ``d``, and some indices ``i_1,...i_k`` in ``{1,...,d}``, the survival copula associated simply reverses its arguments on chosen indices. For exemple, for ``d=4`` and indices ``(2,3)``, we have:
```math
S(u_1,...u_4) = C(u_1,1-u_2,1-u3,u_4)
```
This constructor allows to derive new "survival" families. For exemple, in bivariate cases, this allows to do "rotations". The obtained models can be treated as the starting one, i.e. as a random vector in [0,1]^d with uniforms marginals.
References:
* [nelsen2006](@cite) Nelsen, Roger B. An introduction to copulas. Springer, 2006.
"""
struct SurvivalCopula{d,CT,VI} <: Copula{d}
C::CT
indices::VI
function SurvivalCopula(C,indices)
if typeof(C) == IndependentCopula
return C
end
if length(indices) == 0
return C
end
d = length(C)
@assert all(indices .<= d)
return new{d,typeof(C),typeof(indices)}(C,indices)
end
end
function reverse!(u,idx)
if ndims(u) == 1
for i in idx
u[i] = 1 - u[i]
end
else
for i in idx
u[i,:] .= 1 .- u[i,:]
end
end
return u
end
function reverse(u,idx)
v = deepcopy(u)
reverse!(v,idx)
return v
end
function _cdf(C::SurvivalCopula{d,CT,VI},u) where {d,CT,VI}
i = C.indices[end]
newC = SurvivalCopula(C.C,C.indices[1:end-1])
v = deepcopy(u)
v[i] = 1 - v[i]
r2 = _cdf(newC,v)
v[i] = 1
r1 = _cdf(newC,v)
return r1 - r2
end
Distributions._logpdf(C::SurvivalCopula{d,CT,VI},u) where {d,CT,VI} = Distributions._logpdf(C.C,reverse(u,C.indices))
function Distributions._rand!(rng::Distributions.AbstractRNG, C::SurvivalCopula{d,CT,VI}, x::AbstractVector{T}) where {d,CT,VI,T}
Distributions._rand!(rng,C.C,x)
reverse!(x,C.indices)
end
function Distributions._rand!(rng::Distributions.AbstractRNG, C::SurvivalCopula{d,CT,VI}, A::DenseMatrix{T}) where {d,CT,VI,T}
Distributions._rand!(rng,C.C,A)
reverse!(A,C.indices)
end
function Distributions.fit(T::Type{CT},u) where {CT <: SurvivalCopula}
# d = size(u,1)
d,subCT,indices = T.parameters
subfit = Distributions.fit(subCT,reverse(u,indices))
return SurvivalCopula(subfit,indices)
end