Spaces:
Sleeping
Sleeping
| """ | |
| task3_hard.py | |
| βββββββββββββ | |
| Task 3 β Full Triage Episode (Hard) | |
| """ | |
| from __future__ import annotations | |
| from typing import Callable, Dict, Any, List, Optional, Tuple | |
| from cognitive_env import CogTraceEnv | |
| from patient_simulator import PatientConfig | |
| def _compute_f1(tp: int, fp: int, fn: int) -> float: | |
| precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0 | |
| recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0 | |
| if precision + recall == 0: | |
| return 0.0 | |
| return 2 * precision * recall / (precision + recall) | |
| LEVEL_BONUS_MAP = {3: 1.0, 2: 0.6, 1: 0.3, 0: 0.0} | |
| def grade(results: List[Dict[str, Any]]) -> float: | |
| if not results: | |
| return 0.001 | |
| score = sum(r["score"] for r in results) / len(results) | |
| return max(0.001, min(0.999, score)) | |
| def build_env(seed: int = 0) -> CogTraceEnv: | |
| stage = (seed % 4) + 1 | |
| cfg = PatientConfig( | |
| true_stage=stage, | |
| episode_length=30, | |
| decline_rate=0.01, | |
| noise_level=1.2, | |
| anomaly_day=None, | |
| anomaly_duration=5, | |
| seed=seed, | |
| patient_id=f"task3_seed{seed}", | |
| ) | |
| return CogTraceEnv(config=cfg) | |
| def run_episode( | |
| env: CogTraceEnv, | |
| agent_fn: Callable[[Dict[str, Any], int, List[int]], int], | |
| ) -> Dict[str, Any]: | |
| obs = env.reset() | |
| anomaly_start = env._sim.anomaly_day | |
| anomaly_end = env._sim.anomaly_end | |
| alert_history: List[int] = [] | |
| step = 0 | |
| tp = fp = fn = 0 | |
| level_bonus_total = 0.0 | |
| anomaly_steps = 0 | |
| while True: | |
| obs_dict = obs.model_dump() | |
| action = agent_fn(obs_dict, step, list(alert_history)) | |
| action = max(0, min(3, int(action))) | |
| in_anomaly = anomaly_start <= step < anomaly_end | |
| if in_anomaly: | |
| anomaly_steps += 1 | |
| if action > 0: | |
| tp += 1 | |
| level_bonus_total += LEVEL_BONUS_MAP[action] | |
| else: | |
| fn += 1 | |
| else: | |
| if action > 0: | |
| fp += 1 | |
| alert_history.append(action) | |
| obs, reward, done, info = env.step(action) | |
| step += 1 | |
| if done: | |
| break | |
| f1 = _compute_f1(tp, fp, fn) | |
| level_bonus = (level_bonus_total / anomaly_steps) if anomaly_steps > 0 else 0.0 | |
| score = max(0.001, min(0.999, round(0.70 * f1 + 0.30 * level_bonus, 4))) | |
| return { | |
| "tp": tp, | |
| "fp": fp, | |
| "fn": fn, | |
| "f1_score": round(f1, 4), | |
| "level_bonus": round(level_bonus, 4), | |
| "score": score, | |
| "anomaly_start": anomaly_start, | |
| "anomaly_end": anomaly_end, | |
| } |