Skip to contents

Composes m dfr_dist component distributions into a series system distribution. A series system fails when any component fails, so the system hazard is the sum of component hazards: \(h_{sys}(t) = \sum_j h_j(t)\).

Usage

dfr_dist_series(components, par = NULL, n_par = NULL)

Arguments

components

A list of dfr_dist objects representing system components.

par

Optional concatenated parameter vector \(\theta = (\theta_1, \ldots, \theta_m)\). If NULL, parameters are concatenated from component objects.

n_par

Optional integer vector giving the number of parameters per component. Inferred from component par if not supplied; required when any component has NULL parameters.

Value

A dfr_dist_series object (inherits dfr_dist). Extra fields: $components, $layout, $m, $n_par.

Details

The resulting object inherits from dfr_dist, so all existing methods (hazard, survival, CDF, density, sampling, log-likelihood, MLE fitting) work automatically.

Parameter layout: Parameters are stored as a single concatenated vector. The $layout field maps global indices to component indices. For example, if component 1 has 2 parameters and component 2 has 1, then layout = list(1:2, 3).

Analytical cumulative hazard: If all components provide cum_haz_rate, the series system gets an analytical \(H_{sys}(t) = \sum_j H_j(t)\). Otherwise, falls back to numerical integration.

Score and Hessian: Fall back to numDeriv::grad and numDeriv::hessian on the (correct) composed log-likelihood.

Identifiability: Exponential series systems are not identifiable from system-level data alone — only the sum of rates is identifiable. When fitting to data, check sum(coef(result)) rather than individual rate parameters. Mixed-type series systems (e.g., Weibull + Gompertz) are generally identifiable because the components have different hazard shapes.

Nested series: A dfr_dist_series is itself a dfr_dist, so it can be used as a component in another series system. The resulting nested system's hazard is the sum of all leaf-component hazards.

Class hierarchy: dfr_dist_series inherits from dfr_dist -> likelihood_model -> univariate_dist -> dist. All methods from these parent classes work automatically.

See also

is_dfr_dist_series for the type predicate, ncomponents and component for introspection, param_layout for parameter index mapping, component_hazard for per-component hazard closures, sample_components for sampling component lifetimes, dfr_dist for the parent class constructor, hazard for distribution generics

Other series system: assumptions.dfr_dist_series(), is_dfr_dist_series(), print.dfr_dist_series()

Examples

# \donttest{
library(flexhaz)

# --- Basic exponential series ---
# Three exponential components -> equivalent to single exponential
sys <- dfr_dist_series(list(
    dfr_exponential(0.1),
    dfr_exponential(0.2),
    dfr_exponential(0.3)
))
# System hazard = 0.6 (constant)
h <- hazard(sys)
h(10)  # 0.6
#> [1] 0.6

# System survival at t = 5
S <- surv(sys)
S(5)   # exp(-0.6 * 5)
#> [1] 0.04978707

# --- Mixed Weibull + Gompertz series ---
sys2 <- dfr_dist_series(list(
    dfr_weibull(shape = 2, scale = 100),
    dfr_gompertz(a = 0.01, b = 0.1)
))
h2 <- hazard(sys2)
h2(50)  # sum of Weibull and Gompertz hazards at t=50
#> [1] 1.494132

# --- Nested series ---
subsystem <- dfr_dist_series(list(
    dfr_exponential(0.05),
    dfr_exponential(0.10)
))
full_system <- dfr_dist_series(list(
    subsystem,
    dfr_weibull(shape = 2, scale = 200)
))

# --- Fitting workflow ---
solver <- fit(sys)
# result <- solver(df, par = c(0.1, 0.2, 0.3))
# coef(result)   # fitted parameters
# vcov(result)   # variance-covariance matrix
# logLik(result) # maximized log-likelihood
# }