--- title: "Getting started with kofn" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with kofn} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) set.seed(42) ``` ```{r setup} library(kofn) library(flexhaz) ``` ## What `kofn` does `kofn` is a maximum likelihood estimation toolkit for **k-out-of-n systems**: reliability systems that fail when `k` of `m` components have failed. `k = 1` is a series system (first failure ends it), `k = m` is a parallel system (all must fail), and intermediate values interpolate between them. The package focuses exclusively on inference: log-likelihood, score, Hessian, fit, observation schemes (right/left/interval/periodic), masked cause-of-failure, and Fisher information comparison. The underlying data-generating process (DGP) and topology queries are delegated to `dist.structure`, which kofn imports. ## Your first fit ```{r} # A 2-of-3 exponential system: system fails when 2 of 3 components fail. model <- kofn(k = 2, m = 3, component = dfr_exponential()) # Generate 200 complete (Scheme 0) observations. gen <- rdata(model) df <- gen(theta = c(1, 2, 3), n = 100) # Fit via maximum likelihood. fitter <- fit(model) result <- fitter(df, n_starts = 1) result$converged coef(result) ``` For exponential parallel systems (k = m), only the sum of rates is identifiable from system-level data alone; individual rates are not. The sum typically recovers well: ```{r} sum(coef(result)) sum(c(1, 2, 3)) ``` ## Convention kofn uses the **:F convention**: `k` counts component failures that trigger system failure. - `kofn(k = 1, m)` = series (first failure ends the system). - `kofn(k = m, m)` = parallel (system survives until the m-th failure). - `kofn(k, m)` for intermediate k = k-out-of-m systems. (dist.structure internally uses the :G convention, which is the dual. kofn handles the conversion for you; you never need to think about :G.) ## Observation schemes Real experiments rarely observe system failure exactly. kofn provides composable observation functors for censoring and periodic inspection: ```{r} # Right-censored: systems that fail after tau = 2 get recorded at t = 2 df_cens <- gen(c(1, 2, 3), n = 100, observe = observe_right_censor(tau = 2)) table(df_cens$omega) ``` The log-likelihood handles mixed observation types automatically: ```{r} ll <- loglik(model) ll(df_cens, c(1, 2, 3)) # finite; right-censored obs contribute log S(t) ``` Other functors: `observe_left_censor`, `observe_interval_censor`, `observe_periodic`, `observe_mixture`. See the observation-schemes vignette. ## Weibull components Weibull component lifetimes work analogously, with parameters interleaved as `(shape_1, scale_1, shape_2, scale_2, ...)`: ```{r} model_wei <- kofn(k = 2, m = 2, component = dfr_weibull(), method = "em") gen_wei <- rdata(model_wei) df_wei <- gen_wei(theta = c(1.5, 2.0, 2.0, 3.0), n = 100) result_wei <- fit(model_wei)(df_wei, n_starts = 1) result_wei$shapes result_wei$scales ``` For parallel Weibull systems (`k = m`), `method = "em"` uses an EM algorithm treating the identity of the last-failing component as latent. For general k, use `method = "mle"` (direct L-BFGS-B). ## Periodic inspection (Scheme 1) When only periodic snapshots are available, use `loglik_scheme1`/`fit_scheme1`: ```{r} s1gen <- rdata_scheme1(model) df_s1 <- s1gen(theta = c(1, 2, 3), n = 200, delta = 0.5) ll_s1 <- loglik_scheme1(model) ll_s1(df_s1, c(1, 2, 3)) ``` ## Masked cause-of-failure When you observe system failure and a candidate set (superset of the truly-failed components) rather than knowing which components failed: ```{r} rgen <- rdata_masked(model) df_masked <- rgen(theta = c(1, 2, 3), n = 100, p_mask = 0.3) ll_masked <- loglik_masked(model) ll_masked(df_masked, c(1, 2, 3)) ``` ## Fisher information comparison How much precision do you gain from each observation scheme? kofn provides a built-in comparison: ```{r, eval = FALSE} res <- compare_fisher_info( rates = c(0.5, 0.3), n = 50, delta = 1.0, n_rep = 10, component = dfr_exponential() ) res$median_det ``` This runs `n_rep` replications of each scheme and reports the median determinant of the observed information matrix per scheme. ## What's next See the other vignettes for deeper coverage: - **[Exponential parallel](exponential-parallel.html)**: the IE expansion fast path for parallel exponentials. - **[Observation schemes](observation-schemes.html)**: composable observation functors for complex monitoring setups. - **[Weibull EM](weibull-em.html)**: the EM algorithm details. - **[Periodic inspection](periodic-inspection.html)**: Scheme 1 workflows. - **[dist.structure integration](dist-structure-integration.html)**: how kofn delegates DGP and topology to dist.structure; migration notes for v0.2.0 users. - **[Ecosystem](ecosystem.html)**: how kofn fits with `likelihood.model`, `algebraic.mle`, and `dist.structure`.