README.md

# iohmm-evac

Synthetic hurricane-evacuation household-behavior **data-generating process
(DGP)**, designed to be paired with an Input-Output Hidden Markov Model
(IO-HMM) fit in a later build.

The DGP simulates `N` households over `T` hourly steps before landfall.
Households move through five latent behavioral states (UA → AW → PR → ER →
SH) under exogenous forecasts and warning orders, plus two endogenous
feedbacks (network congestion, peer-departure share). Three observation
channels are emitted each step: a noisy departure indicator, displacement,
and a communication-activity count.

## Quickstart

```bash
uv sync
uv run iohmm-evac scenarios list
uv run iohmm-evac simulate --scenario baseline --seed 0 \
    --output ./output/baseline.parquet
uv run iohmm-evac fit --input ./output/baseline.parquet \
    --output ./output/fit/ --restarts 5
uv run iohmm-evac diagnose recovery --fit ./output/fit/ \
    --truth ./output/baseline.parquet
uv run iohmm-evac report all --input ./output/baseline.parquet \
    --output-dir ./output/figures/
uv run iohmm-evac report recovery-confusion --fit ./output/fit/ \
    --truth ./output/baseline.parquet \
    --output ./output/figures/recovery.png
uv run iohmm-evac sweep run --output-dir ./output/sweep/ --seed 0
uv run iohmm-evac report sweep-all \
    --input-dir ./output/sweep/ \
    --output-dir ./output/figures/

# Production bootstrap (run overnight; ~hours on a 12-core box).
# Substitute --n-replicates 5 for a quick smoke test.
uv run iohmm-evac bootstrap fit \
    --input ./output/baseline.parquet \
    --warm-start ./output/fit/ \
    --output-dir ./output/bootstrap/fits/ \
    --n-replicates 50 --jobs -1 --seed 0
uv run iohmm-evac bootstrap shift-sweep \
    --bootstrap-dir ./output/bootstrap/fits/ \
    --output ./output/bootstrap/shift_sweep.parquet --seed 0
uv run iohmm-evac report bootstrap-bands \
    --input ./output/bootstrap/shift_sweep.parquet \
    --output ./output/figures/bootstrap_bands.png
```

`fit` runs Build 2's IO-HMM EM loop with five restarts and writes a four-file
bundle into `./output/fit/`. `diagnose recovery` aligns the fit's states to
truth and writes `recovery.toml` with state and parameter recovery metrics.
`report all` writes `occupancy.png`, `departures.png`, `trajectories.png`,
and `emissions.png` — the canonical smoke check on the simulator side.
`sweep run` runs every predefined scenario under a common seed; `report
sweep-all` produces Fig. 4 (cross-scenario cumulative departures) and Fig. 5
(2x2 panel of network metrics). See [`docs/sweep.md`](docs/sweep.md) for the
output layout and [`docs/network.md`](docs/network.md) for the metric
definitions.

The final block is the **long-running** Build 4 step: `bootstrap fit` refits
the IO-HMM on B household resamples (joblib parallelism, ~minutes per
replicate at N=10000), `bootstrap shift-sweep` runs B × S simulations under
shifted warning timelines, and `report bootstrap-bands` produces Fig. 6
(failed-evacuation count vs. warning shift, with quantile bands). See
[`docs/bootstrap.md`](docs/bootstrap.md) for the procedure and how to read
the bands.

See [`docs/inference.md`](docs/inference.md) for the math,
[`docs/diagnostics.md`](docs/diagnostics.md) for the recovery diagnostics,
and [`docs/reporting.md`](docs/reporting.md) for the simulator-side plots.

## Layout

* `src/iohmm_evac/` — package source (DGP + inference + diagnostics + report;
  no file > 300 lines).
* `tests/` — pytest suite, ≥ 85% line coverage.
* `docs/` — DGP specification, scenarios, CLI examples, dev notes,
  inference math, recovery diagnostics.

See [`docs/00-overview.md`](docs/00-overview.md) for the pipeline diagram and
pointers into the specification.

## Acceptance gate

```bash
uv run ruff check && uv run ruff format --check && \
    uv run mypy src tests && \
    uv run pytest --cov=src/iohmm_evac --cov-fail-under=85
```

## License

Copyright (C) 2026 SWGY, Inc.

This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License, version 3, as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
General Public License for more details.

The full license text is in [`LICENSE`](LICENSE).
SPDX-License-Identifier: `AGPL-3.0-only`.