---
title: "Explore and reproduce experiments in the Shiny workbench"
author: "R. Heller"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Explore and reproduce experiments in the Shiny workbench}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
resource_files:
- figures/logo.svg
- figures/logo-dark.svg
---
```{r setup, include=FALSE}
set.seed(20260512)
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(shieldR)
```
The shieldR workbench lets you construct an abstract logistics-chain scenario,
compare policy designs, inspect the batch-level evidence, and export the
configuration and results for replay. It calls the same package simulation and
inference functions used in scripted analyses. The interface has no separate
implementation of the model.
## Launch locally
Install the optional dependencies once, then launch from an interactive R
session:
```{r launch, eval=FALSE}
install.packages(c("shiny", "bslib", "DT", "ggplot2"))
shield_app()
```
The application opens in a browser or viewer and runs in the local R process.
Stop the running app from the R console when finished. Arguments after
`launch` are forwarded to `shiny::runApp()`; for explicit local access:
```{r launch-options, eval=FALSE}
shield_app(host = "127.0.0.1", launch.browser = TRUE)
```
Constructing the application without starting a server is useful for testing
or integration with an existing Shiny deployment:
```{r app-object}
app_packages <- c("shiny", "bslib", "DT", "ggplot2")
if (all(vapply(app_packages, requireNamespace, logical(1), quietly = TRUE))) {
app <- shield_app(launch = FALSE)
stopifnot(inherits(app, "shiny.appobj"))
}
```
Uploaded graphs are processed in the running R session. The app uses local
system fonts and does not send inputs to an external analysis service. Hosting
it on another machine changes where that processing occurs. Session state is
not shared between users. Downloads persist only when you save them.
## A first experiment
1. Keep **Balanced resources** as the teaching graph and **Single policy** as
the comparison design. Inspect the displayed batch size, horizon,
replication count and master seed before running.
2. Open **Graph**. The five-leg node and route labels are fixed; inspect the
three numeric input columns. All teaching routes have zero exposure and the
initial item condition controls have zero hazard.
3. Select **Run experiment**. A progress indicator reports simulation and
bootstrap stages. Inputs are validated before the model runs.
4. Read **Outcomes**, then **Diagnostics**. Inspect the summary tables as well
as the plots, especially missing arrival-time counts.
5. Save the **Complete experiment RDS** and **Replay script R** from **Data
and export**. They preserve the settings actually used by the completed run.
The balanced teaching example inspects transport mechanics. It does not contain
calibrated logistics parameters. Switch to
**Constrained resources** to examine resource scarcity and a shorter suggested
horizon without introducing hazards.
Changing the teaching graph replaces its vehicle fractions and suggested
horizon; it does not reset other settings you have edited. Review those settings
before interpreting the new run.
## Configure the graph and assumptions
The **Graph** table has exactly the seven columns accepted by
`shield_parameters()`: `leg`, `from`, `to`, `route`, `travel_min`,
`exposure_weight` and `vehicle_fraction`. The topology requires 15 unique
leg-route rows.
Double-click a numeric cell to edit it. Changing `vehicle_fraction` updates all
three routes within that leg, because the fleet belongs to the leg. The
constructor rounds fleet size up and enforces at least two vehicles per leg.
A graph CSV can be imported or exported; import requires that same schema and
is limited to 64 KB. Invalid edits and uploads produce an explanatory message
and preserve the previous valid graph.
You can prepare a compatible neutral CSV from R:
```{r graph-export}
scenario <- example_scenario()
graph_columns <- c("leg", "from", "to", "route", "travel_min",
"exposure_weight", "vehicle_fraction")
graph_file <- tempfile("shieldR-graph-", fileext = ".csv")
utils::write.csv(scenario$graph[graph_columns], graph_file, row.names = FALSE)
imported <- utils::read.csv(graph_file, stringsAsFactors = FALSE,
check.names = FALSE)
stopifnot(inherits(shield_parameters(imported), "shield_parameters"))
```
The sidebar groups controls by purpose:
| Group | What it controls |
|---|---|
| Batches and reproducibility | Batch size, replication count, administrative horizon and master seed |
| Observation and dispatch | Reassessment, observation error, dispatch interval, allowable holds, loading/unloading and the policy response parameter |
| Item-condition assumptions | Explicit loss and class-escalation rates |
| Disruption assumptions | Disruption enablement, baseline probability, conditional destructiveity, delay and disruption-response assumptions |
A maximum hold must be a multiple of the dispatch interval. Parameters not
exposed by the form retain their documented constructor defaults, including the
rounded class mix, and are recorded in the complete experiment bundle. The
form sets the two named disruption risk levels to the same entered baseline and selects
the low label. Use `shield_parameters()` in an R script when your design needs
separate disruption risk levels or other settings not exposed by the form.
The app does not import previously saved results as a new interactive session.
Read experiment RDS files in R and use the replay script for a new run.
## Choose the comparison design
| Design | Seed structure and output |
|---|---|
| Single policy | One arm, descriptive outcomes and diagnostics; no policy contrast |
| Independent policy arms | Select two to four distinct policies; arm seeds increment from the master seed; all selected pairwise Stage 2 comparisons are reported |
| Paired disruptions-disabled intervention | One policy run with disruptions enabled and disabled; matching seeds, parameters and replication counts; paired viability contrast |
For independent arms, the **Comparisons** view reports Mann-Whitney U, Cliff's
delta and the median difference with percentile bootstrap 95% intervals.
Positive effects favor `arm_x` for the viability endpoint. All displayed
pairwise Stage 2 comparisons constitute one explicit Benjamini-Hochberg FDR
family. Three or more arms also produce a Kruskal-Wallis H statistic, degrees
of freedom and p-value. This interactive family is separate from the
comparison families declared in a separate scripted study.
For the paired design, the contrast is **no disruptions minus disruptions**, expressed
as a paired mean difference of batch viability proportions. The interval
resamples matched replication indices jointly. The paired design controls
disruption enablement itself, regardless of the ordinary disruption checkbox. The
neutral graph has zero exposure, so its paired contrast is zero.
All comparison intervals use 10,000 bootstrap resamples. The statistical unit
is the batch replication. Small interactive experiments can produce unstable
estimates or point intervals on discrete outcomes; more bootstrap resamples do
not compensate for an inadequate number of independent replications.
## Read each view together with its limitations
| View | Evidence to inspect |
|---|---|
| Graph | The current input graph; it can differ from the graph of the last completed run |
| Outcomes | Batch points and boxplots for Stage 1, 2 and 3 arrival-viable proportions; valid counts, median and quartiles |
| Comparisons | Independent or paired effect estimates and intervals; raw and adjusted log p-values; optional multi-arm omnibus |
| Diagnostics | Fleet utilization by leg, conditional arrival times and the complete remaining endpoint summaries with missing counts |
| Data and export | Individual batch rows, seed schedule, software provenance and downloadable results |
| Methods and help | Policy information assumptions, endpoint definitions, inferential limits and reproducibility instructions |
The primary endpoint is arrival viable at Stage 2 by the horizon. Physical arrival
precedes unloading and ends item-condition hazard. A nonarrival is not necessarily
a loss. Conditional arrival-time medians exclude items who never arrived;
undefined batch medians remain missing. `n_pending` counts items still viable
without Stage 3 arrival. `n_disruption_loss` counts destructive disruption events and is not the
paired total intervention effect.
After you edit an input, a visible message identifies the results as belonging
to the last completed experiment. Run again to apply the new configuration.
Experiment downloads retain that last completed run; the graph download is
explicitly the **current** graph. Starting a new run clears the old experiment,
so a failed validation cannot silently attach old results to new assumptions.
## Export an experiment you can replay
| Download | Contents and use |
|---|---|
| Complete experiment RDS | Schema version, full input/configuration, arm schedule, original `shield_run` objects, summaries, comparisons, omnibus output and session/software/RNG provenance |
| Replay script R | Explicit constructor arguments and arm schedule; recreates batch results and descriptive summaries; saves `shieldR_replayed.rds` |
| Batch results CSV | One row per batch with arm label, seeds, identifiers and outcomes |
| Summaries CSV | Median/IQR summaries, valid and missing counts by endpoint and arm |
| Comparisons CSV | Complete pairwise or paired comparison rows; empty for a single-policy run |
| Viability figure PNG / PDF | Current completed experiment's viability plot, with 600 dpi PNG and vector PDF |
The replay script reproduces simulations and descriptive summaries. The RDS
bundle also retains inferential tables and the omnibus result; retain it for
a complete audit record. Use the same package source/environment to reproduce
results exactly. The PNG/PDF downloads cover the viability figure; diagnostics
and batch tables remain available in the bundle for your own plotting.
After saving the experiment to a chosen analysis output directory, inspect it
from R:
```{r inspect-download, eval=FALSE}
bundle <- readRDS("shieldR_experiment.rds")
bundle$config$arms
bundle$provenance$shieldR_version
bundle$provenance$session_info
bundle$summary
bundle$comparisons
bundle$omnibus
# Reproduce the first arm from the recorded request.
arm <- bundle$config$arms[1, ]
replayed <- simulate_shield(
bundle$config$parameters,
policy = arm$policy, disruption_model = arm$disruption_model,
n_rep = bundle$config$settings$n_rep, seed = arm$seed,
disruptions_enabled = arm$disruptions_enabled
)
stopifnot(identical(replayed, bundle$runs[[1]]))
```
## Move a larger experiment into scripts
The workbench accepts 1 to 60 items per batch, 2 to 100 replications per arm
and horizons from 1 to 240 minutes. The combined workload is limited to
`items * horizon * replications * arms <= 250000` as an interactive safeguard.
This is a conservative input-size measure, not an exact runtime estimate.
These caps apply to the app, not to the underlying package APIs.
Use scripted studies for larger grids, durable checkpoints, parameter
uncertainty analyses, custom comparison families or publication exports. The
[study design tutorial](study-design.html) explains batch-level inference and
replay. Study integrations require their own versioned validation and interface checks. The interface and its synthetic examples
do not establish application-specific validity.
```{r session-information}
sessionInfo()
```