--- title: "Composition and substitution" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Composition and substitution} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` ```{r setup} library(dist.structure) library(algebraic.dist) ``` ## Building new systems from old dist.structure provides two compositional operations: - `substitute_component(sys, j, new_component)` swaps one component's distribution while preserving the topology. - `compose_systems(outer, inner_list)` replaces each component of the outer system with an inner sub-system, flattening the components and enumerating the composed minimal paths. These let you build hierarchical reliability networks without writing min_paths by hand. ## Substituting a component Start with a 3-component parallel system, then upgrade one component to a longer-lived Weibull: ```{r} sys <- parallel_dist(list( exponential(1), exponential(1), exponential(1) )) # Survival at t = 1 for the all-exponential parallel: algebraic.dist::surv(sys)(1) sys2 <- substitute_component(sys, j = 1, new_component = weibull_dist(shape = 2, scale = 2)) # Survival improves because component 1 is now longer-lived: algebraic.dist::surv(sys2)(1) ``` `substitute_component` returns a `coherent_dist` with the same min_paths and the modified component list. Topology queries work identically: ```{r} length(min_paths(sys2)) # still 3 (parallel) ncomponents(sys2) # still 3 ``` ## Hierarchical composition `compose_systems` nests: give an outer topology and a list of inner systems (one per outer component), and get back a flattened system whose min_paths combine both levels of topology. ### Series of parallels A common redundant design: two parallel blocks in series. ```{r} inner_a <- parallel_dist(list(exponential(1), exponential(1))) inner_b <- parallel_dist(list(exponential(1), exponential(1))) # Outer: series of 2 "slots" (the components are placeholder; they get # replaced by the inners during compose_systems). outer <- series_dist(list(exponential(1), exponential(1))) sys <- compose_systems(outer, list(inner_a, inner_b)) ncomponents(sys) # 4 total leaf components length(min_paths(sys)) # 4 composed paths ``` The composed paths are the Cartesian product of inner paths within each outer path. Outer path is `{1, 2}`; inner_a min_paths = `{1}, {2}`; inner_b shifted min_paths = `{3}, {4}`. Four combinations: `{1, 3}, {1, 4}, {2, 3}, {2, 4}`. ```{r} min_paths(sys) ``` ### Parallel of series The dual: two series blocks in parallel. ```{r} inner_a <- series_dist(list(exponential(1), exponential(1))) inner_b <- series_dist(list(exponential(1), exponential(1))) outer <- parallel_dist(list(exponential(1), exponential(1))) sys <- compose_systems(outer, list(inner_a, inner_b)) ncomponents(sys) # 4 total length(min_paths(sys)) # 2 composed paths min_paths(sys) # {1, 2} and {3, 4} ``` ## Mixing a sub-system with a plain dist `compose_systems` handles a mix of `dist_structure` inner systems and plain `dist` inner components. A plain `dist` is treated as a single- component atomic sub-system: ```{r} # Series of: (a 2-parallel block) + (a single exponential) inner_par <- parallel_dist(list(exponential(1), exponential(1))) outer <- series_dist(list(exponential(1), exponential(1))) sys <- compose_systems(outer, list(inner_par, exponential(1))) ncomponents(sys) # 3: two from parallel + one single min_paths(sys) # {1, 3} and {2, 3} ``` Component 3 is the atomic component from the second outer slot; it must function jointly with either component 1 or component 2 for the system to function. ## Arbitrary depth Composition is arbitrarily nestable: ```{r} # A parallel of two different sub-systems: sub_a <- series_dist(list(exponential(1), exponential(1))) # simple series sub_b <- bridge_dist(replicate(5, exponential(1), simplify = FALSE)) # bridge outer <- parallel_dist(list(exponential(1), exponential(1))) combined <- compose_systems(outer, list(sub_a, sub_b)) ncomponents(combined) # 2 + 5 = 7 total length(min_paths(combined)) # = 1 + 4 (series has 1 path, bridge has 4) ``` The structural richness compounds: you can analyze the whole system via the full dist.structure protocol (sampler, surv, system_signature, importance measures, dual, etc.). ## Substitution vs composition - **`substitute_component`**: same topology, different component distribution. Use when exploring sensitivity to a single component's parameters or swapping one family for another. - **`compose_systems`**: richer topology by nesting. Use when the system has hierarchical structure (redundant subsystems, modular designs, networks of networks). Both produce objects that participate in the full dist.structure protocol, so further substitutions and compositions compose cleanly.