Spaces:
Sleeping
Sleeping
| """ | |
| task2_medium.py | |
| βββββββββββββββ | |
| Task 2 (Medium) β Anomaly Timing Detection | |
| The agent observes a 7-day behavioral time series and must decide | |
| on which day to raise its first alert (action >= 1). | |
| Grading (continuous 0.0β1.0): | |
| Alert on exact anomaly day β 1.00 | |
| Alert within Β±1 day β 0.75 | |
| Alert within Β±2 days β 0.50 | |
| Alert within Β±3 days β 0.25 | |
| Alert outside anomaly window β 0.00 | |
| No alert raised in 7 days β 0.00 | |
| """ | |
| from __future__ import annotations | |
| from typing import List, Dict, Any, Optional | |
| import sys, os | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) | |
| from env.cognitive_env import CogTraceEnv | |
| from env.patient_simulator import PatientConfig, make_medium_patient | |
| TASK_ID = "task2_medium" | |
| TASK_NAME = "Anomaly Timing Detection" | |
| DIFFICULTY = "medium" | |
| DESCRIPTION = ( | |
| "Observe a 7-day stream of patient behavioral signals. " | |
| "Raise an alert (action 1β3) on the day you detect an anomaly. " | |
| "Scored on how close your first alert is to the true anomaly onset." | |
| ) | |
| def _timing_score(alert_day: Optional[int], anomaly_day: int) -> float: | |
| if alert_day is None: | |
| return 0.0 | |
| diff = abs(alert_day - anomaly_day) | |
| if diff == 0: return 1.00 | |
| if diff == 1: return 0.75 | |
| if diff == 2: return 0.50 | |
| if diff == 3: return 0.25 | |
| return 0.00 | |
| def run_episode(env: CogTraceEnv, agent_fn) -> Dict[str, Any]: | |
| """ | |
| Run a 7-step episode and find the first alerting step. | |
| agent_fn : callable(observation_dict, step: int) -> int | |
| Returns action 0β3 for each step. | |
| """ | |
| obs = env.reset() | |
| first_alert_day: Optional[int] = None | |
| trajectory = [] | |
| for step in range(env.config.episode_length): | |
| action = int(agent_fn(obs.model_dump(), step)) | |
| action = max(0, min(3, action)) | |
| next_obs, reward, done, info = env.step(action) | |
| trajectory.append({ | |
| "step": step, | |
| "action": action, | |
| "anomaly_active": info.anomaly_active, | |
| "reward": reward.value, | |
| }) | |
| if action > 0 and first_alert_day is None: | |
| first_alert_day = step | |
| obs = next_obs | |
| if done: | |
| break | |
| anomaly_day = env._sim.anomaly_day | |
| score = _timing_score(first_alert_day, anomaly_day) | |
| return { | |
| "first_alert_day": first_alert_day, | |
| "anomaly_day": anomaly_day, | |
| "score": score, | |
| "trajectory": trajectory, | |
| } | |
| def grade(trajectory: List[Dict[str, Any]]) -> float: | |
| """ | |
| Grade a list of episode result dicts. | |
| Each dict must contain: | |
| - "first_alert_day" : int or None | |
| - "anomaly_day" : int | |
| Returns mean timing score in [0.0, 1.0]. | |
| """ | |
| if not trajectory: | |
| return 0.0 | |
| scores = [_timing_score(r["first_alert_day"], r["anomaly_day"]) for r in trajectory] | |
| return round(sum(scores) / len(scores), 4) | |
| def build_env(seed: int = 0) -> CogTraceEnv: | |
| sim = make_medium_patient(seed) | |
| return CogTraceEnv(config=sim.config) | |
| if __name__ == "__main__": | |
| import random | |
| results = [] | |
| for seed in range(20): | |
| env = build_env(seed) | |
| result = run_episode( | |
| env, | |
| agent_fn=lambda obs, step: random.choices([0, 0, 0, 1], k=1)[0] | |
| ) | |
| results.append(result) | |
| final = grade(results) | |
| print(f"[Task 2] Random baseline score: {final:.4f}") | |
| print("Expected ~0.15β0.30 (random rarely hits the right day)") | |