{
"cells": [
{
"cell_type": "markdown",
"id": "b4150bf9",
"metadata": {},
"source": [
"# Ensemble Resilience Comparison\n",
"\n",
"Compare stochastic playback statistics across synthetic small, medium, and large scenarios."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "62390b55",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-05T12:57:20.082691Z",
"iopub.status.busy": "2026-10-05T12:57:20.082577Z",
"iopub.status.idle": "2026-10-05T12:57:23.429304Z",
"shell.execute_reply": "2026-10-05T12:57:23.428554Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" tier | \n",
" mean_production | \n",
" std_production | \n",
" mean_downtime_hours | \n",
" samples | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" small | \n",
" 28.699000 | \n",
" 0.000000 | \n",
" 0.0 | \n",
" 6 | \n",
"
\n",
" \n",
" | 1 | \n",
" medium | \n",
" 20.356423 | \n",
" 5.607148 | \n",
" 0.0 | \n",
" 12 | \n",
"
\n",
" \n",
" | 2 | \n",
" large | \n",
" 15.579618 | \n",
" 3.308869 | \n",
" 0.0 | \n",
" 18 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" tier mean_production std_production mean_downtime_hours samples\n",
"0 small 28.699000 0.000000 0.0 6\n",
"1 medium 20.356423 5.607148 0.0 12\n",
"2 large 15.579618 3.308869 0.0 18"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import sys\n",
"from pathlib import Path\n",
"\n",
"PROJECT_ROOT = Path.cwd().resolve()\n",
"while PROJECT_ROOT != PROJECT_ROOT.parent and not (PROJECT_ROOT / \"pyproject.toml\").exists():\n",
" PROJECT_ROOT = PROJECT_ROOT.parent\n",
"if not (PROJECT_ROOT / \"pyproject.toml\").exists():\n",
" raise RuntimeError(\n",
" \"Notebook must be executed within a FHOPS checkout (pyproject.toml not found).\"\n",
" )\n",
"if str(PROJECT_ROOT) not in sys.path:\n",
" sys.path.insert(0, str(PROJECT_ROOT))\n",
"\n",
"import pandas as pd\n",
"from IPython.display import display\n",
"\n",
"from docs.examples.analytics import utils\n",
"from fhops.scenario.synthetic import SyntheticDatasetConfig\n",
"\n",
"SCENARIOS = [\n",
" (\n",
" \"small\",\n",
" PROJECT_ROOT / \"examples/synthetic/small/scenario.yaml\",\n",
" PROJECT_ROOT / \"docs/examples/analytics/data/synthetic_small_sa_assignments.csv\",\n",
" ),\n",
" (\n",
" \"medium\",\n",
" PROJECT_ROOT / \"examples/synthetic/medium/scenario.yaml\",\n",
" PROJECT_ROOT / \"docs/examples/analytics/data/synthetic_medium_sa_assignments.csv\",\n",
" ),\n",
" (\n",
" \"large\",\n",
" PROJECT_ROOT / \"examples/synthetic/large/scenario.yaml\",\n",
" PROJECT_ROOT / \"docs/examples/analytics/data/synthetic_large_sa_assignments.csv\",\n",
" ),\n",
"]\n",
"\n",
"summary_rows = []\n",
"ensemble_tables = {}\n",
"for tier, scenario_path, assign_path in SCENARIOS:\n",
" config = SyntheticDatasetConfig(\n",
" name=f\"synthetic-{tier}\", tier=tier, num_blocks=8, num_days=12, num_machines=4\n",
" )\n",
" tables, sampling = utils.run_stochastic_summary(scenario_path, assign_path, tier=tier)\n",
" ensemble_tables[tier] = tables\n",
" production = tables.shift.groupby(\"sample_id\")[\"production_units\"].sum()\n",
" downtime = tables.shift.groupby(\"sample_id\")[\"downtime_hours\"].sum()\n",
" summary_rows.append(\n",
" {\n",
" \"tier\": tier,\n",
" \"mean_production\": production.mean(),\n",
" \"std_production\": production.std(),\n",
" \"mean_downtime_hours\": downtime.mean(),\n",
" \"samples\": tables.shift[\"sample_id\"].nunique(),\n",
" }\n",
" )\n",
"summary_df = pd.DataFrame(summary_rows)\n",
"summary_df"
]
},
{
"cell_type": "markdown",
"id": "d6173e42",
"metadata": {},
"source": [
"## Production Distributions"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "2911a00e",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-05T12:57:23.431143Z",
"iopub.status.busy": "2026-10-05T12:57:23.430967Z",
"iopub.status.idle": "2026-10-05T12:57:23.455082Z",
"shell.execute_reply": "2026-10-05T12:57:23.454486Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
""
],
"text/plain": [
"alt.Chart(...)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
""
],
"text/plain": [
"alt.Chart(...)"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
""
],
"text/plain": [
"alt.Chart(...)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"for tier, tables in ensemble_tables.items():\n",
" prod = tables.shift.groupby(\"sample_id\")[\"production_units\"].sum()\n",
" display(\n",
" utils.plot_distribution(\n",
" prod, title=f\"{tier.title()} Production Distribution\", xlabel=\"Production Units\"\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "01ac8336",
"metadata": {},
"source": [
"## Downtime Summary"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "01ef7a7f",
"metadata": {
"execution": {
"iopub.execute_input": "2026-10-05T12:57:23.456551Z",
"iopub.status.busy": "2026-10-05T12:57:23.456436Z",
"iopub.status.idle": "2026-10-05T12:57:23.465866Z",
"shell.execute_reply": "2026-10-05T12:57:23.465351Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" small | \n",
" medium | \n",
" large | \n",
"
\n",
" \n",
" \n",
" \n",
" | count | \n",
" 6.0 | \n",
" 12.0 | \n",
" 18.0 | \n",
"
\n",
" \n",
" | mean | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | std | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | min | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | 25% | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | 50% | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | 75% | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | max | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" small medium large\n",
"count 6.0 12.0 18.0\n",
"mean 0.0 0.0 0.0\n",
"std 0.0 0.0 0.0\n",
"min 0.0 0.0 0.0\n",
"25% 0.0 0.0 0.0\n",
"50% 0.0 0.0 0.0\n",
"75% 0.0 0.0 0.0\n",
"max 0.0 0.0 0.0"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"downtime_summary = pd.DataFrame(\n",
" {\n",
" tier: tables.shift.groupby(\"sample_id\")[\"downtime_hours\"].sum()\n",
" for tier, tables in ensemble_tables.items()\n",
" }\n",
")\n",
"downtime_summary.describe()"
]
}
],
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}