Angshuman28's picture
Upload folder using huggingface_hub
f6ae66b verified
|
Raw
History Blame Contribute Delete
4.78 kB
# mm.md β€” 6-step walkthrough on `outbreak_easy`
Run: `uv run python mm.py`
## Setup
- **Task:** `outbreak_easy`, **seed=0**, `max_ticks=12`.
- **Initial latent state** (per `server/simulator/tasks.py`): R1 hot
with `Iβ‰ˆ0.03` (~30 cases / 1000 pop); R2 / R3 / R4 quiet with
`Iβ‰ˆ0.001` (~1 case / 1000 pop).
- **Initial resources:** 1000 test_kits, 500 hospital_beds, 20 mobile_units,
2000 vaccine_doses.
- **Telemetry:** delay = 1 tick, Οƒ_cases = 0.02 (β‰ˆ Β±20 cases of noise),
Οƒ_compliance = 0.05.
The `cases` field printed each tick is **delayed and noisy** β€” it's
`reported_cases_d_ago`. The reward is computed on the latent ground
truth, not the telemetry, so reward dynamics may not visibly match
the printed cases.
## Step-by-step intent
### Step 1 β€” `NoOp` baseline
- **Intent:** see how the env evolves with no intervention.
- **Expected:** R1 grows slowly under R0=1.5 (within-region Ξ² β‰ˆ 0.3);
R2-R4 stay near zero. Reward should be high (most population still
susceptible, low total infection).
### Step 2 β€” `DeployResource(R1, test_kits, 200)`
- **Intent:** test_kits efficacy is `0.00002 / unit / tick`; 200 units
contribute `-0.004` to R1's I per tick over 2 ticks.
- **Expected:** kits inventory drops 1000 β†’ 800. Reward changes are
too small to read off β€” this is mostly to demonstrate the deployment
flow (`accepted=True`, inventory delta).
### Step 3 β€” `RestrictMovement(R1, moderate)`
- **Intent:** severity multiplier = 0.25 β†’ R0_eff on R1 drops 25%.
Slows transmission inside R1.
- **Expected:** `active_restrictions` shows `R1=moderate(4)` (4-tick
duration, decremented each tick). R1 case-growth slows. Compliance
starts gentle decay under restriction.
### Step 4 β€” `DeployResource(R1, vaccine_doses, 500)`
- **Intent:** vaccine efficacy `0.0001 / unit`; 500 units β†’ `-0.05` Ξ”I
on R1 plus equivalent S β†’ R conversion.
- **Expected:** vax inventory 2000 β†’ 1500. R1's hospital_load eases
over the next 2 ticks; R1 compliance_proxy holds steady.
### Step 5 β€” `Escalate(national)`
- **Intent:** unlocks the `restrict_movement.strict` rule via the L1
legal_constraints entry. SEIR is a no-op for this tick.
- **Expected:** `accepted=True`. Internally
`escalation_unlocked_strict=True`. The `legal_constraints` list
still contains L1 in the observation (it's the rule, not the lock
state); only the lock has flipped.
### Step 6 β€” `RestrictMovement(R1, strict)`
- **Intent:** severity multiplier = 0.5 β†’ R0_eff on R1 drops 50%.
Pre-step-5 this would have been `accepted=False` (legal-violation).
- **Expected:** `accepted=True`. R1's restriction flips
`moderate β†’ strict`. Compliance starts faster decay
(-0.03 / tick under strict).
## Reading the output
Each step prints:
| Field | Meaning |
|---|---|
| `action` | `kind` of payload submitted |
| `accepted` | env's verdict (False = V2-illegal **or** legal-violation **or** insufficient resource) |
| `reward` | per-tick `outer_reward` ∈ [0, 1] (design §15 weighted sum) |
| `regions` | `cases` (delayed + noisy), `hosp` (current), `comp` (noisy) |
| `resources` | global inventory (test_kits / hospital_beds_free / mobile_units / vaccine_doses) |
| `restricts` | active restrictions per region with `(ticks_remaining)` |
| `tick` | `current / max_ticks`; `done` is True only at terminal |
The reward has **6 components** weighted (per design Β§15):
| Component | Weight | What it measures |
|---|---|---|
| `r_infect` | 0.35 | `1 - mean(I)` β€” average infection across regions |
| `r_time` | 0.18 | `1 - tick / max_ticks` β€” early-tick bias |
| `r_hosp` | 0.17 | `1 - mean(hospital_load)` |
| `r_casc` | 0.15 | binary: 1 if no region exceeds I=0.30, else 0 |
| `r_policy` | 0.12 | binary: 1 if last action accepted, else 0 |
| `r_fair` | 0.03 | `1 - pstdev(I)` β€” equality across regions |
Because `outbreak_easy` starts low-infection and the 3-consecutive-
safe-ticks rule fires quickly, **the env may report `done=True`
before all 6 steps are exhausted**. The script keeps stepping
regardless so you see the full intended sequence; in production the
agent would break on `done`.
## Caveats
- **Telemetry noise on tick 0:** the printed `R1: cases=48` at the
initial state can exceed the true 30 cases per 1000 because of the
Gaussian noise draw. Different seeds will print different numbers
for the same latent state.
- **Compliance proxy** is similarly noised β€” small fluctuations don't
reflect real compliance changes.
- **Reward stays high throughout** even though `done=True` flips
early; the success-terminal +0.20 bonus is **not** included in
`obs.reward` (per the env-step separation pin from Session 7d) β€”
it's composed downstream by the trainer in `reward_shaping.py`.