--- title: "quantify()-ing probabilities" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{quantify()-ing probabilities} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( comment = "#>", message = FALSE, warning = FALSE, fig.width = 7, fig.height = 4, fig.align = "center", dpi = 300 ) ``` With `prob = TRUE`, [`quantify()`](https://tidyfault.netlify.app/reference/quantify.html) treats each column as a **failure probability** for that basic event and returns the **top-event probability** for each row (assuming independence in the fast implementation). This vignette shows: 1. Turning binary scenario tables into probability tables with [`populate()`](https://tidyfault.netlify.app/reference/populate.html). 2. Projecting probabilities over time from hourly rates (IT security example). ## Database example: `populate()` then `quantify()` [`db_probs`](https://tidyfault.netlify.app/reference/db_probs.html) is in long form (`event`, `probability`). [`populate()`](https://tidyfault.netlify.app/reference/populate.html) replaces 1s in a binary scenario with those probabilities (0 stays 0): ```{r} library(tidyfault) library(dplyr) library(ggplot2) library(tidyr) library(tibble) data("db_nodes") data("db_edges") data("db_outcomes_binary") data("db_probs") f <- curate(db_nodes, db_edges) |> equate() |> formulate() db_outcomes_probs <- populate(db_outcomes_binary, db_probs) knitr::kable(head(db_outcomes_probs, 6), digits = 3) ``` Then pass the probability matrix to `quantify()`: ```{r} prob_top <- quantify(f, newdata = db_outcomes_probs, prob = TRUE) prob_top summary(prob_top) ``` --- ## IT security: rates to cumulative probabilities over time The next chunk defines illustrative constant failure rates per hour (same orders of magnitude as the JSS article). For each mission time `t`, map rates to **cumulative** failure probabilities with the exponential distribution $P(T \le t) = 1 - e^{-\lambda t}$: ```{r} data("it_security_nodes") data("it_security_edges") f_sec <- formulate(equate(curate(it_security_nodes, it_security_edges))) # Illustrative constant failure rates (per hour), as in the paper source it_security_rates <- tibble::tibble( DA = 0.25 / 24 / 365, EP = 0.20 / 24 / 365, IM = 0.09 / 24 / 365, LR = 0.13 / 24 / 365, MN = 0.29 / 24 / 365, PO = 0.16 / 24 / 365, PC = 0.22 / 24 / 365, PM = 0.15 / 24 / 365, VS = 0.11 / 24 / 365, WB = 0.17 / 24 / 365 ) rate_names <- names(it_security_rates) t_hours <- seq(0, 50000, by = 1000) it_security_projections <- crossing(t = t_hours, it_security_rates) |> mutate(across(all_of(rate_names), ~ pexp(q = t, rate = .x))) it_security_projections$outcome <- quantify( f_sec, newdata = it_security_projections[, rate_names, drop = FALSE], prob = TRUE ) it_security_projections |> select(t, outcome) |> head(6) ``` Plot top-event probability versus time: ```{r} ggplot(it_security_projections, aes(x = t, y = outcome)) + geom_line() + labs( x = "Time (hours)", y = "Top-event probability" ) ``` --- ## Summary | Task | Approach | |------|----------| | Scenario-specific event probabilities | `populate()` from binary + long `event` / `probability` table | | Direct probability scenarios | Data frame of probabilities + `quantify(..., prob = TRUE)` | | Time profiles | Build rows of $P(\text{event})$ at each $t$, then same call | Uncertainty simulation is covered in [Simulating uncertainty](https://tidyfault.netlify.app/articles/simulating-uncertainty).