Spaces:
Sleeping
Sleeping
| """ | |
| FairRecovery β Scenario Definitions. | |
| Three scenarios of increasing difficulty. The HARD scenario is the | |
| "fairness trap": a naive utility-maximising agent will always pick | |
| Zone 0 (easy to fix, low vulnerability) and miss Zone 4 (severely | |
| damaged, highest vulnerability). The trained agent must learn to | |
| prioritise vulnerability Γ damage jointly. | |
| Structure matches OpenEnv reference env (hallucination-detector-gym) tasks.py. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass, field | |
| from typing import Dict, List | |
| from .constants import Difficulty | |
| class ScenarioConfig: | |
| """Immutable task configuration for one scenario.""" | |
| task_id: str | |
| difficulty: Difficulty | |
| description: str | |
| initial_budget: float | |
| zones: List[Dict] | |
| hint: str = "" # hints shown to the agent in observations | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Scenario Registry | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| TASKS: Dict[str, ScenarioConfig] = { | |
| "easy": ScenarioConfig( | |
| task_id = "easy_3zone", | |
| difficulty = Difficulty.EASY, | |
| description= ( | |
| "3-zone post-flood scenario. One zone has moderate damage " | |
| "and high vulnerability. Straightforward resource allocation." | |
| ), | |
| initial_budget = 80.0, | |
| hint = "Focus on the zone with highest vulnerability Γ damage.", | |
| zones = [ | |
| {"zone_id": 0, "damage": 0.30, "service": 0.70, "vulnerable_ratio": 0.15}, | |
| {"zone_id": 1, "damage": 0.80, "service": 0.20, "vulnerable_ratio": 0.85}, # <- critical | |
| {"zone_id": 2, "damage": 0.20, "service": 0.80, "vulnerable_ratio": 0.10}, | |
| ], | |
| ), | |
| "medium": ScenarioConfig( | |
| task_id = "medium_5zone", | |
| difficulty = Difficulty.MEDIUM, | |
| description= ( | |
| "5-zone earthquake scenario. Multiple zones damaged. " | |
| "Budget is constrained β agent must triage effectively." | |
| ), | |
| initial_budget = 60.0, | |
| hint = "Budget is limited. Prioritise zones with high damage AND vulnerability.", | |
| zones = [ | |
| {"zone_id": 0, "damage": 0.40, "service": 0.60, "vulnerable_ratio": 0.30}, | |
| {"zone_id": 1, "damage": 0.70, "service": 0.30, "vulnerable_ratio": 0.75}, # <- high priority | |
| {"zone_id": 2, "damage": 0.50, "service": 0.50, "vulnerable_ratio": 0.50}, | |
| {"zone_id": 3, "damage": 0.65, "service": 0.35, "vulnerable_ratio": 0.65}, # <- high priority | |
| {"zone_id": 4, "damage": 0.15, "service": 0.85, "vulnerable_ratio": 0.20}, | |
| ], | |
| ), | |
| "hard": ScenarioConfig( | |
| task_id = "hard_5zone_fairness_trap", | |
| difficulty = Difficulty.HARD, | |
| description= ( | |
| "5-zone hurricane scenario β FAIRNESS TRAP. " | |
| "Zone 0 is wealthy (moderate damage, very low vulnerability). " | |
| "Zone 4 is poor (severe damage, extremely high vulnerability). " | |
| "A naive utility-maximiser will fix Zone 0 first (easier ROI). " | |
| "A fairness-aware agent prioritises Zone 4 (higher vulnerability Γ damage)." | |
| ), | |
| initial_budget = 45.0, | |
| hint = ( | |
| "FAIRNESS TRAP: Zone 0 looks easy to fix but has very low vulnerability. " | |
| "Zone 4 has highest damage AND highest vulnerability β prioritise it." | |
| ), | |
| zones = [ | |
| # Zone 0: wealthy district β moderate damage, very easy to restore, low vulnerability | |
| {"zone_id": 0, "damage": 0.35, "service": 0.65, "vulnerable_ratio": 0.08}, | |
| # Zone 1: middle class | |
| {"zone_id": 1, "damage": 0.50, "service": 0.50, "vulnerable_ratio": 0.40}, | |
| # Zone 2: mixed | |
| {"zone_id": 2, "damage": 0.60, "service": 0.40, "vulnerable_ratio": 0.55}, | |
| # Zone 3: poor district | |
| {"zone_id": 3, "damage": 0.72, "service": 0.28, "vulnerable_ratio": 0.72}, | |
| # Zone 4: informal settlement β severe damage, highest vulnerability (TRAP zone) | |
| {"zone_id": 4, "damage": 0.92, "service": 0.08, "vulnerable_ratio": 0.96}, | |
| ], | |
| ), | |
| } | |
| def get_task(difficulty: str) -> ScenarioConfig: | |
| """Retrieve scenario config by difficulty string.""" | |
| task = TASKS.get(difficulty) | |
| if task is None: | |
| raise ValueError( | |
| f"Unknown difficulty '{difficulty}'. " | |
| f"Choose from: {list(TASKS.keys())}" | |
| ) | |
| return task | |