CogTraceEnv_ / task3_hard.py
Hashblue's picture
Upload folder using huggingface_hub
a523ae1 verified
Raw
History Blame Contribute Delete
2.67 kB
"""
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,
}