RohitChandramouli6618 commited on
Commit
c2e4262
Β·
1 Parent(s): f52daca

Add README.md

Browse files
Files changed (1) hide show
  1. README.md +191 -29
README.md CHANGED
@@ -8,46 +8,208 @@ app_port: 7860
8
  pinned: false
9
  ---
10
 
11
- # Cascade Containment
12
 
13
- An RL benchmark for epidemic containment policy under uncertainty.
14
- A city health authority must allocate limited resources across districts
15
- to contain a spreading outbreak β€” with delayed data, resource scarcity,
16
- and cascading hospital stress.
17
 
18
- Generalises to wildfire deployment, cyberattack isolation, and misinformation containment.
19
 
20
- ## Environment
21
 
22
- - **3 tasks:** Easy (2 districts), Medium (4 districts), Hard (6 districts with 3-day data lag)
23
- - **Action space:** `action_type` (test/restrict/allocate) + `district_id`
24
- - **Learning:** GRPO-style episodic memory with advantage gating
25
 
26
- ## Usage
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- \```python
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  from client import CascadeContainmentEnv
30
  from models import ContainmentAction
31
 
32
- with CascadeContainmentEnv(base_url="https://YOUR-SPACE-URL.hf.space").sync() as env:
 
 
 
33
  obs = env.reset(task_name="easy")
34
- result = env.step(ContainmentAction(action_type="allocate", district_id=0))
35
- \```
 
 
 
 
 
 
 
 
36
 
37
- ## Tasks
 
 
 
 
 
 
38
 
39
- | Task | Districts | Steps | Resources | Data Lag |
40
- |------|-----------|-------|-----------|----------|
41
- | easy | 2 | 10 | 10 | None |
42
- | medium | 4 | 15 | 8 | None |
43
- | hard | 6 | 20 | 7 | 3 days |
44
 
45
- ## Reward Function
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
- | Term | Value | Condition |
48
- |------|-------|-----------|
49
- | Infection penalty | -0.50 | Per district above 0.4 threshold |
50
- | Hospital breach | -1.00 | Per breached hospital |
51
- | Early containment | +0.50 | Scaled by time remaining |
52
- | Unnecessary restriction | -0.20 | Restricting below 0.2 threshold |
53
- | Correct prioritisation | +0.30 | Allocating to highest-infected district |
 
8
  pinned: false
9
  ---
10
 
11
+ # 🦠 Cascade Containment
12
 
13
+ > An RL benchmark for sequential resource allocation under spreading cascade dynamics.
 
 
 
14
 
15
+ A city health authority must allocate limited resources across districts to contain a spreading outbreak β€” with delayed data, resource scarcity, and cascading hospital stress. Designed as a **generalizable benchmark**: the same environment mechanics model wildfire resource deployment, cyberattack isolation, and misinformation containment.
16
 
17
+ Built for the **Meta PyTorch OpenEnv Hackathon x SST 2026**.
18
 
19
+ ---
 
 
20
 
21
+ ## The Problem
22
+
23
+ Sequential resource allocation under uncertainty is one of the most common and consequential decision problems in the real world. Whether containing an epidemic, deploying firefighting crews, or isolating a cyberattack β€” the agent faces the same fundamental challenge:
24
+
25
+ - Resources are scarce and cannot cover every district simultaneously
26
+ - Data is delayed β€” by the time a crisis is visible, it has already grown
27
+ - Interventions have cascading effects across adjacent areas
28
+ - Acting too late is catastrophic; acting too early wastes resources
29
+
30
+ No existing OpenEnv benchmark formalizes this problem class. Cascade Containment does.
31
+
32
+ ---
33
+
34
+ ## Environment Design
35
+
36
+ ### Action Space
37
+ One decision per step β€” kept deliberately simple to maximize strategic depth:
38
+
39
+ | Field | Type | Values |
40
+ |-------|------|--------|
41
+ | `action_type` | string | `"test"` Β· `"restrict"` Β· `"allocate"` |
42
+ | `district_id` | int | 0-indexed district target |
43
+
44
+ - **test** β€” spend 1 resource to get accurate infection data for a district
45
+ - **restrict** β€” impose movement restriction (free, but penalised if infection is low)
46
+ - **allocate** β€” deploy 1 resource unit to reduce spread rate this step
47
+
48
+ ### Observation Space
49
+ The agent receives a filtered, potentially lagged view of the world β€” never the full ground truth:
50
+ ```python
51
+ CityObservation:
52
+ districts: List[DistrictObservation] # per-district visible state
53
+ available_resources: int # budget remaining this turn
54
+ current_step: int
55
+ max_steps: int
56
+ done: bool
57
+ reward: float | None
58
+ message: str | None # human-readable feedback
59
+ ```
60
+
61
+ Each `DistrictObservation` contains:
62
+ - `reported_infection_rate` β€” real-time (easy/medium) or **3 days lagged** (hard)
63
+ - `growth_rate_hint` β€” noisy signal of true spread rate
64
+ - `hospital_capacity_remaining` β€” always accurate (hospitals report in real time)
65
+ - `tested_recently`, `restriction_active`
66
+
67
+ ### The Key Design Decision: Partial Observability
68
+ The hard task exposes infection rates from **3 days ago**. The agent must learn to act on noisy forward signals (`growth_rate_hint`) rather than react to confirmed data β€” exactly the challenge real public health officials face. This single mechanic is what separates a thoughtful agent from a reactive one.
69
+
70
+ ---
71
+
72
+ ## Three Tasks
73
+
74
+ | Task | Districts | Steps | Resources | Data Lag | Challenge |
75
+ |------|-----------|-------|-----------|----------|-----------|
76
+ | `easy` | 2 | 10 | 10 | None | Single outbreak, clear signal |
77
+ | `medium` | 4 | 15 | 8 | None | Two simultaneous outbreaks, forced triage |
78
+ | `hard` | 6 | 20 | 7 | 3 days | Scarce resources, invisible acceleration |
79
+
80
+ ---
81
+
82
+ ## Reward Function
83
+
84
+ Five shaped reward terms fire independently each step, providing dense feedback throughout the episode:
85
+
86
+ | Term | Value | Purpose |
87
+ |------|-------|---------|
88
+ | Infection penalty | `-0.50` per district above threshold | Primary containment signal |
89
+ | Hospital breach | `-1.00` per collapsed hospital | Catastrophic failure deterrent |
90
+ | Early containment | `+0.50 Γ— (1 - step/max_steps)` | Teaches proactive behaviour |
91
+ | Unnecessary restriction | `-0.20` | Prevents lazy blanket lockdowns |
92
+ | Correct prioritisation | `+0.30` | Rewards triage intelligence |
93
+
94
+ The early containment bonus decays over time β€” containing an outbreak on day 3 is worth more than on day 8. This single design decision is what teaches the agent to act before crises emerge rather than after.
95
+
96
+ ---
97
+
98
+ ## Grader
99
 
100
+ The grader is fully deterministic β€” no randomness, no LLM calls β€” producing a weighted composite score in `[0.0, 1.0]`:
101
+
102
+ | Component | Weight | Measures |
103
+ |-----------|--------|---------|
104
+ | Containment score | 45% | District-days below infection threshold |
105
+ | Hospital score | 30% | Capacity preserved across episode |
106
+ | Efficiency score | 15% | Resources directed to high-need districts |
107
+ | Speed score | 10% | Containment achieved faster than max steps |
108
+
109
+ ---
110
+
111
+ ## Baseline Agent β€” GRPO-Style Episodic Memory
112
+
113
+ The baseline uses a **simulated GRPO learning loop** with episodic memory β€” no weight updates required:
114
+
115
+ 1. **Rollout 1** runs with base prompt, no prior knowledge
116
+ 2. After each rollout, compute advantage = `R_i - mean(completed rollouts)`
117
+ 3. If above average β†’ store positive-reward steps into `EpisodicMemory`
118
+ 4. If below average β†’ suppress, memory unchanged
119
+ 5. Next rollout retrieves the 3 most similar past situations by L1 distance on infection profiles and injects them as concrete examples into the prompt
120
+
121
+ The prompt is the policy. Memory updates are the policy improvement. This produces measurably better decisions across rollouts without any gradient computation.
122
+
123
+ ---
124
+
125
+ ## Baseline Scores
126
+
127
+ Dumb greedy policy (always allocates to district 0):
128
+
129
+ | Task | Score | Hospital Breached |
130
+ |------|-------|-------------------|
131
+ | Easy | ~0.50 | No |
132
+ | Medium | ~0.23 | Yes |
133
+ | Hard | ~0.21 | Yes |
134
+
135
+ A smart LLM agent using the episodic memory baseline consistently scores 0.65–0.80 on easy and shows meaningful improvement on medium across rollouts.
136
+
137
+ ---
138
+
139
+ ## Usage
140
+ ```python
141
  from client import CascadeContainmentEnv
142
  from models import ContainmentAction
143
 
144
+ with CascadeContainmentEnv(
145
+ base_url="https://RohitChandramouli6618-cascade-containment.hf.space"
146
+ ).sync() as env:
147
+ # Run easy task
148
  obs = env.reset(task_name="easy")
149
+
150
+ while not obs.done:
151
+ action = ContainmentAction(
152
+ action_type="allocate",
153
+ district_id=0
154
+ )
155
+ result = env.step(action)
156
+ obs = result.observation
157
+ print(f"Reward: {result.reward:.4f}")
158
+ ```
159
 
160
+ ### Running the Full Evaluation
161
+ ```bash
162
+ # Set required environment variables
163
+ export API_BASE_URL="https://router.huggingface.co/v1"
164
+ export MODEL_NAME="meta-llama/Llama-3.1-8B-Instruct"
165
+ export HF_TOKEN="your_hf_token"
166
+ export ENV_BASE_URL="https://RohitChandramouli6618-cascade-containment.hf.space"
167
 
168
+ # Run inference
169
+ python inference.py
170
+ ```
 
 
171
 
172
+ ---
173
+
174
+ ## Generalisation
175
+
176
+ This environment is not epidemic-specific. The core mechanics β€” spreading cascade, delayed data, resource scarcity, spatial spillover β€” are identical to:
177
+
178
+ - **Wildfire deployment** β€” pre-position crews before fire reaches populated areas
179
+ - **Cyberattack isolation** β€” quarantine systems before lateral movement completes
180
+ - **Misinformation containment** β€” deploy corrections before false narratives entrench
181
+ - **Poverty intervention** β€” allocate aid where need is growing, not just where it's visible
182
+
183
+ The environment is designed to be a lasting benchmark for this general problem class, not a pandemic novelty.
184
+
185
+ ---
186
+
187
+ ## Project Structure
188
+ ```
189
+ epidemic_containment_env/
190
+ β”œβ”€β”€ models.py # Data contracts (Action, Observation, State)
191
+ β”œβ”€β”€ constants.py # All numeric configuration
192
+ β”œβ”€β”€ client.py # Client-side interface
193
+ β”œβ”€β”€ openenv.yaml # Environment manifest
194
+ β”œβ”€β”€ inference.py # Evaluation entry point
195
+ β”œβ”€β”€ server/
196
+ β”‚ β”œβ”€β”€ environment.py # Core RL loop
197
+ β”‚ β”œβ”€β”€ grader.py # Deterministic scorer
198
+ β”‚ β”œβ”€β”€ utils.py # Spread computation, observation builder
199
+ β”‚ β”œβ”€β”€ app.py # FastAPI server
200
+ β”‚ β”œβ”€β”€ Dockerfile
201
+ β”‚ └── tasks/ # Easy / Medium / Hard task definitions
202
+ β”œβ”€β”€ baseline/
203
+ β”‚ β”œβ”€β”€ policy.py # LLM agent with prompt engineering
204
+ β”‚ β”œβ”€β”€ evaluator.py # GRPO episodic memory loop
205
+ β”‚ └── run.py # CLI entry point
206
+ └── core/
207
+ β”œβ”€β”€ trajectory.py # EpisodicMemory class
208
+ β”œβ”€β”€ reward.py # Score normalisation
209
+ └── policy_update.py # Advantage computation
210
+ ```
211
+
212
+ ---
213
 
214
+ ## Tags
215
+ `reinforcement-learning` Β· `resource-allocation` Β· `sequential-decision-making` Β· `partial-observability` Β· `cascade-dynamics` Β· `openenv` Β· `llm-agent`