## ----setup, include = FALSE--------------------------------------------------- knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ## ----model-------------------------------------------------------------------- library(likelihood.contr) library(likelihood.model) # m = 3 components. Candidate set columns: x1, x2, x3 (logical). m <- 3 masked_exact <- contr_fn( loglik = function(df, par, ...) { C <- as.matrix(df[, paste0("x", seq_len(m))]) lambda_c <- rowSums(sweep(C, 2, par, `*`)) lambda_sys <- sum(par) sum(log(lambda_c) - lambda_sys * df$t) }, score = function(df, par, ...) { C <- as.matrix(df[, paste0("x", seq_len(m))]) lambda_c <- rowSums(sweep(C, 2, par, `*`)) # d/d(lambda_j): sum(C[i,j] / lambda_c[i]) - n * t_bar colSums(C / lambda_c) - sum(df$t) } ) masked_right <- contr_fn( loglik = function(df, par, ...) { -sum(par) * sum(df$t) }, score = function(df, par, ...) { rep(-sum(df$t), m) } ) model <- likelihood_contr( obs_type = "omega", exact = masked_exact, right = masked_right, assumptions = c( "independent exponential components", "series system", "C1: true cause always in candidate set", "C2: symmetric masking", "C3: masking independent of parameters" ) ) model ## ----simulate----------------------------------------------------------------- set.seed(42) n <- 300 true_rates <- c(1.0, 0.5, 0.3) censor_time <- 2.0 mask_prob <- 0.4 # probability a non-failed component enters candidate set # Generate component lifetimes and system lifetime comp_times <- matrix(rexp(n * m, rate = rep(true_rates, each = n)), n, m) sys_times <- apply(comp_times, 1, min) failed_comp <- apply(comp_times, 1, which.min) # Apply right-censoring obs_times <- pmin(sys_times, censor_time) omega <- ifelse(sys_times <= censor_time, "exact", "right") # Generate candidate sets satisfying C1/C2/C3 C <- matrix(FALSE, n, m) for (i in seq_len(n)) { if (omega[i] == "exact") { C[i, failed_comp[i]] <- TRUE # C1 others <- setdiff(seq_len(m), failed_comp[i]) C[i, others] <- runif(length(others)) < mask_prob # C2/C3 } # right-censored: candidate set stays empty } df <- data.frame(t = obs_times, omega = omega, C) colnames(df)[3:(m + 2)] <- paste0("x", seq_len(m)) cat("Exact:", sum(omega == "exact"), " Right-censored:", sum(omega == "right"), "\n") head(df) ## ----fit---------------------------------------------------------------------- result <- fit(model)(df, par = c(0.5, 0.5, 0.5)) summary(result) ## ----compare------------------------------------------------------------------ cat("True rates: ", paste(true_rates, collapse = ", "), "\n") cat("Estimated: ", paste(round(coef(result), 3), collapse = ", "), "\n")