The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Non-coherent systems: cold standby

library(dist.structure)
library(algebraic.dist)

Why “non-coherent”

The structure-function framework assumes a monotone binary function phi: {0, 1}^m -> {0, 1} that maps per-component states to a system state. This captures a huge class of reliability topologies but not everything practitioners build. Cold standby is a canonical example.

A cold standby system has m components but only one is active at a time. When the active component fails, a dormant spare instantaneously takes over. System lifetime is the sum of component lifetimes, not an order statistic.

The topology is temporal succession, not a structure function on states. So cold standby:

dist.structure provides cold_standby_dist for this case, with its own class chain that deliberately does not inherit dist_structure.

Constructing a cold standby

sys <- cold_standby_dist(list(
  exponential(1),
  exponential(2),
  exponential(0.5)
))
class(sys)
#> [1] "cold_standby_dist" "univariate_dist"   "continuous_dist"  
#> [4] "dist"
dist.structure::is_dist_structure(sys)   # FALSE -- not a coherent system
#> [1] FALSE

Mean and sampling: exact

mean is exact when every component has an exact mean method: it sums the component means.

mean(sys)                              # 1/1 + 1/2 + 1/0.5 = 3.5
#> [1] 3.5

The sampler is also exact: independent samples from each component, summed.

set.seed(1)
x <- algebraic.dist::sampler(sys)(5000)
mean(x)                                # empirical ~ 3.5
#> [1] 3.505092

Survival and CDF: Monte Carlo with caching

For general components, the density of a sum-of-independent-RVs has no closed form (it’s a convolution). dist.structure computes surv and cdf via Monte Carlo sampling. The closure caches the samples on the first call, so repeated evaluations at different t values are deterministic given the same mc:

set.seed(42)
S <- algebraic.dist::surv(sys)
S(c(1, 2, 3, 5), mc = 5000)           # survival at multiple t values
#> [1] 0.9332 0.7136 0.4986 0.2104

A different mc triggers a fresh draw:

S(2, mc = 5000)                        # uses the same cache
#> [1] 0.7136
S(2, mc = 10000)                       # new cache with 10000 samples
#> [1] 0.7104

Because the cache lives inside the closure, using the same S closure keeps results consistent. cdf has its own closure and its own cache: cdf(sys)(t) + surv(sys)(t) computed independently is not exactly 1. If you need that identity, use one surv closure and compute the CDF from it:

S <- algebraic.dist::surv(sys)
F_t <- function(t) 1 - S(t)
F_t(2) + S(2)                          # exactly 1
#> [1] 1

For reproducibility across separate closure constructions, seed before each one:

set.seed(1); S1 <- algebraic.dist::surv(sys); s1 <- S1(2)
set.seed(1); S2 <- algebraic.dist::surv(sys); s2 <- S2(2)
all.equal(s1, s2)
#> [1] TRUE

Specialized closed-form case: iid exponentials

A cold standby of m iid Exp(rate) components has system lifetime Gamma(shape = m, rate = rate):

m <- 4; rate <- 2
sys <- cold_standby_dist(replicate(m, exponential(rate), simplify = FALSE))
# Monte Carlo survival at t = 3
set.seed(1)
mc_est <- algebraic.dist::surv(sys)(3, mc = 10000)
# Exact via Gamma
exact <- pgamma(3, shape = m, rate = rate, lower.tail = FALSE)
cat(sprintf("MC: %.4f, Exact: %.4f\n", mc_est, exact))
#> MC: 0.1522, Exact: 0.1512

If you hit this case often, you can avoid the Monte Carlo by constructing an algebraic.dist::gamma_dist directly.

What cold standby does NOT support

Generics requiring topology or component-level density/sup fail cleanly:

dist.structure::phi(sys, c(1, 1, 1, 1))
#> Error in UseMethod("phi"): no applicable method for 'phi' applied to an object of class "c('cold_standby_dist', 'univariate_dist', 'continuous_dist', 'dist')"
dist.structure::min_paths(sys)
#> Error in UseMethod("min_paths"): no applicable method for 'min_paths' applied to an object of class "c('cold_standby_dist', 'univariate_dist', 'continuous_dist', 'dist')"

Methods inherited from algebraic.dist::univariate_dist that require density or sup (notably vcov, expectation) are also not supported by default. A specialized subclass with a closed-form aggregate (e.g., iid exponential -> Gamma) can provide them by overriding.

When to reach for cold standby

When you need the full dist.structure protocol (topology, importance, composition), cold standby is the wrong tool; use a coherent system instead.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.