The following demonstrates how to use the rmo
package to
generate samples from a multivariate Marshall–Olkin distribution.
Simple usage
Sampling from one of the integrated family of extendible Marshall–Olkin distributions is simple. For example, the following code generates a sample of size 10 from a trivariate extendible Marshall–Olkin distribution from the so-called \(\alpha\)-stable family with parameter \(\alpha = 0.4\):
rpextmo(10, 3, eta = 0.4, family = "AlphaStable")
#> [,1] [,2] [,3]
#> [1,] 1.76166384 1.76166384 1.76166384
#> [2,] 2.29274538 1.65792149 3.41241836
#> [3,] 0.83385548 0.83385548 0.83385548
#> [4,] 0.32498008 0.32498008 0.32498008
#> [5,] 1.58113094 1.58113094 1.58113094
#> [6,] 1.96768969 1.96768969 0.31779119
#> [7,] 0.02560441 0.02560441 0.02560441
#> [8,] 0.52896593 2.44176858 0.52896593
#> [9,] 0.08884174 0.79477742 0.08884174
#> [10,] 1.65539156 1.65539156 1.65539156
The jump distribution parameter eta
usually allows for a
range of possible depenence structures.
Extended usage
Each integrated family of extendible Marshall–Olkin distributions has the additional parameters
-
a
(default: 0) for the killing rate, -
b
(default: 0) for the * drift*, and -
gamma
(default: 1) for the intensity scaling parameter.
We cite (Sloot 2022) for a better understanding of these parameters:
For this, recall that we can characterize every ext. MO distribution by a Bernstein function \(\psi\), which defines the law of a (potentially killed) Lévy subordinator. Components corresponding to the ext. MO distributed random vector are killed once the subordinator passes their individual unit exponential barrier values. For compound Poisson subordinators, we distinguish subordinator laws by their jump intensity and jump size distribution: The jump intensity translates into the overall speed with which the subordinator surpasses the barrier values. Thus, it corresponds to the random vector’s marginal rate. The distribution of jump sizes predefines the chances of the subordinator simultaneously surpassing multiple barrier values, and therefore, it corresponds to the random vector’s dependence structure. Simply put, a high probability of larger jumps increases the chance of simultaneous deaths, while a high probability of smaller jumps increases the likelihood of individual deaths. This logic culminates into the pure-drift and pure-killing corner cases, corresponding to the independence and comonotonicity, respectively, pure-jump Lévy subordinators with infinite activity, which can be approximated by compound Poisson processes, and convex combinations of those above.
The following code generates a sample of size 10 from a trivariate extendible Marshall–Olkin distribution from the (extended) \(\alpha\)-stable family with parameter \(\alpha = 0.4\), killing rate \(a = 0.1\), drift \(b = 0.2\), and intensity scaling parameter \(\gamma = 0.5\):
rpextmo(
10, 3,
a = 0.1, b = 0.2, gamma = 0.5,
eta = 0.4, family = "AlphaStable",
)
#> [,1] [,2] [,3]
#> [1,] 5.7394990 2.6272176 3.6620668
#> [2,] 1.1123593 1.7227713 1.7227713
#> [3,] 2.7849008 2.7849008 2.7849008
#> [4,] 0.3664178 0.6315217 0.6315217
#> [5,] 1.7496377 1.7496377 0.8216942
#> [6,] 0.2419438 0.2419438 0.2419438
#> [7,] 0.2198191 0.2198191 0.2198191
#> [8,] 0.6055010 4.3828162 1.6956795
#> [9,] 0.2372185 0.2372185 0.2372185
#> [10,] 3.2767102 1.9154214 0.9063151
Advance usage
Aside from the integrated families, the rmo
package also
provides tools to create custom extendible Marshall–Olkin distributions
via so-called Bernstein functions. For example, the following
code generates the Bernstein function associated with the \(\alpha\)-stable family with parameter
\(\alpha = 0.4\) from the simple
example above:
AlphaStableBernsteinFunction(0.4)
#> An object of class "AlphaStableBernsteinFunction"
#> - alpha: 0.4
The class of Bernstein functions is closed under addition, scalar multiplication, and composite scalar multiplication. This allows recombinations of implemented Bernstein functions to create new ones. For example, the following code creates the Bernstein function associated with the \(\alpha\)-stable family with parameter \(\alpha = 0.4\), killing rate \(a = 0.1\), drift \(b = 0.2\), and intensity scaling parameter \(\gamma = 0.5\):
SumOfBernsteinFunctions(
SumOfBernsteinFunctions(
ConstantBernsteinFunction(0.1),
LinearBernsteinFunction(0.2)
),
ScaledBernsteinFunction(
0.5,
AlphaStableBernsteinFunction(0.4)
)
)
#> An object of class "SumOfBernsteinFunctions"
#> - first:
#> An object of class "SumOfBernsteinFunctions"
#> - first:
#> An object of class "ConstantBernsteinFunction"
#> - constant: 0.1
#> - second:
#> An object of class "LinearBernsteinFunction"
#> - scale: 0.2
#> - second:
#> An object of class "ScaledBernsteinFunction"
#> - scale: 0.5
#> - original:
#> An object of class "AlphaStableBernsteinFunction"
#> - alpha: 0.4
To generate a sample from this custom extendible Marshall–Olkin
distribution, use the rextmo
function:
rextmo(10, 3,
SumOfBernsteinFunctions(
SumOfBernsteinFunctions(
ConstantBernsteinFunction(0.1),
LinearBernsteinFunction(0.2)
),
ScaledBernsteinFunction(
0.5,
AlphaStableBernsteinFunction(0.4)
)
)
)
#> [,1] [,2] [,3]
#> [1,] 1.89291113 0.73199879 2.11799065
#> [2,] 0.11377987 0.04674430 0.11377987
#> [3,] 0.03386182 0.03386182 0.03386182
#> [4,] 0.08256332 0.44866035 0.44866035
#> [5,] 0.31735915 0.06744323 0.31735915
#> [6,] 0.08547364 0.40515098 0.40515098
#> [7,] 0.32959507 0.32959507 0.32959507
#> [8,] 0.07251348 0.07251348 0.07251348
#> [9,] 0.37937632 2.72986765 1.41231581
#> [10,] 1.36677394 0.96929648 0.96929648
Extending rmo
The rmo
package is designed to be easily extensible.
Consider the following Bernstein function (No. 28 in Chp. 16 in (Schilling, Song, and Vondracek 2012)): \[
\psi(x)
= \log{\frac{b {(x + a)}}{a {(x + b)}}},
0 < a < b.
\]
It is a complete Bernstein function with Lévy density \(\nu\): \[ \nu{(u)} = {\left[ e^{-a u} - e^{-b u} \right]} / {u}, u > 0 , \] and with the Stieljtes density \(\sigma\): \[ \sigma{(u)} = 1_{(a, b)}{(u)} / {u}, u > 0 . \]
It is not implemented in the package, but it can be added as follows:
CustomBernsteinFunction <- setClass( # nolint
"CustomBernsteinFunction",
contains = "CompleteBernsteinFunction",
slots = c(a = "numeric", b = "numeric"),
validity = function(object) {
if (object@a <= 0) {
stop("a must be positive")
}
if (object@b <= 0) {
stop("b must be positive")
}
if (object@a >= object@b) {
stop("a must be less than b")
}
invisible(TRUE)
}
)
setMethod(
"initialize",
signature(.Object = "CustomBernsteinFunction"),
function(.Object, a, b) { # nolint
if (!missing(a) && !missing(b)) {
.Object@a <- a # nolint
.Object@b <- b # nolint
validObject(.Object)
}
invisible(.Object)
}
)
setMethod(
"show",
"CustomBernsteinFunction",
function(object) {
cat(sprintf("An object of class %s\n", classLabel(class(object))))
if (isTRUE(validObject(object, test = TRUE))) {
cat(sprintf("- a: %s\n", format(object@a)))
cat(sprintf("- b: %s\n", format(object@b)))
} else {
cat("invalid or not initialized object\n")
}
invisible(NULL)
}
)
setMethod(
"getLevyDensity",
"CustomBernsteinFunction",
function(object) {
structure(
function(u) {
(exp(-object@a * u) - exp(-object@b * u)) / u
},
lower = 0, upper = Inf, type = "continuous"
)
}
)
setMethod(
"getStieltjesDensity",
"CustomBernsteinFunction",
function(object) {
structure(
function(u) {
ifelse(u > object@a & u < object@b, 1 / u, 0)
},
lower = object@a, upper = object@b, type = "continuous"
)
}
)
setMethod(
"calcValue",
"CustomBernsteinFunction",
function(object, x, cscale = 1, ...) {
x <- cscale * x
log((object@b * (x + object@a)) / (object@a * (x + object@b)))
}
)
setMethod(
"getDefaultMethodString",
"CustomBernsteinFunction",
function(object) {
"stieltjes"
}
)
Now we can create a custom Bernstein function object and generate samples from it:
bf <- CustomBernsteinFunction(a = 0.5, b = 2)
rextmo(10, 3, bf)
#> [,1] [,2] [,3]
#> [1,] 4.5124306 0.6776867 0.6776867
#> [2,] 1.6510005 1.6510005 1.7551740
#> [3,] 0.8254936 0.8254936 0.6441104
#> [4,] 1.3517013 1.3517013 1.3517013
#> [5,] 2.5269475 2.5269475 1.9062638
#> [6,] 4.5057099 2.4365320 1.7672876
#> [7,] 1.6811601 1.6811601 1.6811601
#> [8,] 0.1955646 0.3424441 0.3424441
#> [9,] 0.5672961 0.5672961 0.5672961
#> [10,] 1.9118335 3.3807612 1.9118335
rexmo(10, 3, calcExShockSizeArrivalIntensities(bf, 3, method = "levy"))
#> [,1] [,2] [,3]
#> [1,] 0.621524066 3.576891392 0.621524066
#> [2,] 1.725156021 0.711134685 0.711134685
#> [3,] 0.041547469 0.518341738 0.041547469
#> [4,] 0.431265509 0.431265509 0.431265509
#> [5,] 0.009924545 0.009924545 0.009924545
#> [6,] 3.788789729 3.788789729 3.788789729
#> [7,] 0.868756834 0.930285358 0.930285358
#> [8,] 0.828216388 0.828216388 1.246066232
#> [9,] 0.041924976 0.041924976 0.041924976
#> [10,] 1.212388226 1.498387190 1.212388226
rexmo(10, 3, calcExShockSizeArrivalIntensities(bf, 3, method = "stieltjes"))
#> [,1] [,2] [,3]
#> [1,] 3.5263329 2.7646248 4.7625102
#> [2,] 0.3084601 0.7489434 0.7489434
#> [3,] 1.6212391 0.6477563 1.6212391
#> [4,] 0.1090898 0.1090898 0.1090898
#> [5,] 0.7484761 0.7484761 0.7484761
#> [6,] 0.1174769 0.1174769 0.1174769
#> [7,] 0.8045211 2.2488587 1.8485112
#> [8,] 0.6993002 0.6993002 0.6993002
#> [9,] 3.1630755 3.1630755 3.1630755
#> [10,] 3.7058646 3.7058646 3.7058646