feat: implement episode grader and update inference scoring to enforce strict (0.01, 0.99) bounds
Browse files- inference.py +6 -4
- tasks/grader.py +9 -1
inference.py
CHANGED
|
@@ -147,13 +147,15 @@ def run_task(name: str, env: SentinelEnv) -> float:
|
|
| 147 |
assignments_str = ", ".join(f"{a.sensor_id}→{a.target_id}" for a in actions) if actions else "none"
|
| 148 |
print(f"[STEP] [{source.upper()}] Assignments: {assignments_str} | Reward: {reward:+.1f}")
|
| 149 |
|
| 150 |
-
|
| 151 |
-
|
|
|
|
|
|
|
| 152 |
print(f"\n Total Reward : {total_reward:.1f}")
|
| 153 |
print(f" Steps : {info['step_count']}")
|
| 154 |
print(f" LLM steps : {llm_steps} | Greedy fallback: {greedy_steps}")
|
| 155 |
print(f" Missed HIGH : {len(info['missed_targets'])}")
|
| 156 |
-
print(f" SCORE : {score:.4f} (0.
|
| 157 |
return score
|
| 158 |
|
| 159 |
|
|
@@ -180,4 +182,4 @@ if __name__ == "__main__":
|
|
| 180 |
print(f" {name:<8} {score:.4f} {bar}")
|
| 181 |
print(f"\n Average: {sum(results.values()) / len(results):.4f}")
|
| 182 |
print(f"{'='*50}")
|
| 183 |
-
print("[END]")
|
|
|
|
| 147 |
assignments_str = ", ".join(f"{a.sensor_id}→{a.target_id}" for a in actions) if actions else "none"
|
| 148 |
print(f"[STEP] [{source.upper()}] Assignments: {assignments_str} | Reward: {reward:+.1f}")
|
| 149 |
|
| 150 |
+
raw_score = grade_episode(total_reward, info["step_count"], num_sensors=env.initial_sensor_count)
|
| 151 |
+
# Strictly clamp within (0.0, 1.0) — validator rejects exactly 0.0 or 1.0
|
| 152 |
+
score = max(0.01, min(0.99, float(raw_score)))
|
| 153 |
+
|
| 154 |
print(f"\n Total Reward : {total_reward:.1f}")
|
| 155 |
print(f" Steps : {info['step_count']}")
|
| 156 |
print(f" LLM steps : {llm_steps} | Greedy fallback: {greedy_steps}")
|
| 157 |
print(f" Missed HIGH : {len(info['missed_targets'])}")
|
| 158 |
+
print(f" SCORE : {score:.4f} (strictly in 0.01 – 0.99)")
|
| 159 |
return score
|
| 160 |
|
| 161 |
|
|
|
|
| 182 |
print(f" {name:<8} {score:.4f} {bar}")
|
| 183 |
print(f"\n Average: {sum(results.values()) / len(results):.4f}")
|
| 184 |
print(f"{'='*50}")
|
| 185 |
+
print("[END]")
|
tasks/grader.py
CHANGED
|
@@ -8,10 +8,18 @@ def grade_episode(total_reward: float, steps: int, num_sensors: int = 5) -> floa
|
|
| 8 |
"""Normalize total_reward to a float strictly in (0, 1)."""
|
| 9 |
if steps <= 0 or num_sensors <= 0:
|
| 10 |
return 0.5
|
|
|
|
| 11 |
max_reward = steps * num_sensors * 2.0
|
|
|
|
| 12 |
min_reward = steps * -2.0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
if max_reward == min_reward:
|
| 14 |
raw_score = 0.5
|
| 15 |
else:
|
| 16 |
raw_score = (total_reward - min_reward) / (max_reward - min_reward)
|
| 17 |
-
|
|
|
|
|
|
|
|
|
| 8 |
"""Normalize total_reward to a float strictly in (0, 1)."""
|
| 9 |
if steps <= 0 or num_sensors <= 0:
|
| 10 |
return 0.5
|
| 11 |
+
|
| 12 |
max_reward = steps * num_sensors * 2.0
|
| 13 |
+
<<<<<<< HEAD
|
| 14 |
min_reward = steps * -2.0
|
| 15 |
+
=======
|
| 16 |
+
min_reward = steps * num_sensors * -2.0
|
| 17 |
+
|
| 18 |
+
>>>>>>> 2fc3fc6 (feat: implement episode grader and update inference scoring logic to enforce normalized bounds)
|
| 19 |
if max_reward == min_reward:
|
| 20 |
raw_score = 0.5
|
| 21 |
else:
|
| 22 |
raw_score = (total_reward - min_reward) / (max_reward - min_reward)
|
| 23 |
+
|
| 24 |
+
# Strictly clamp within (0.0, 1.0) — never exactly 0.0 or 1.0
|
| 25 |
+
return max(0.01, min(0.99, float(raw_score)))
|