atrium-sim-webviz / train /evaluate.py
chicelli's picture
bootstrap: atrium-sim webviz API (Gradio SDK, ZeroGPU)
a7d3d15 verified
Raw History Blame Contribute Delete
2.86 kB
"""Evaluation: run a policy over a held-out spec suite on fixed seeds.
Seeds are enumerated from a fixed base so every checkpoint and baseline sees
IDENTICAL walls - eval numbers are comparable across the whole project.
uv run python -m train.evaluate --policy oracle --suite interp --episodes 20
uv run python -m train.evaluate --checkpoint runs/x/ckpt.pt --suite interp
"""
from __future__ import annotations
import argparse
import json
import statistics
import gymnasium as gym
import atrium_sim # noqa: F401
from atrium_sim.blueprint import _SUITES
BASE_SEED = 10000
METRIC_KEYS = ("episode_return", "frac_in_tol", "frac_filled", "waste_frac",
"completed", "score", "mean_abs_dev_mm")
def evaluate(env, policy, suite: str, episodes: int) -> dict:
"""Round-robin the suite's specs on fixed seeds; aggregate terminal metrics."""
specs = _SUITES[suite]
per_episode: list[dict] = []
for i in range(episodes):
spec = specs[i % len(specs)]
obs, info = env.reset(seed=BASE_SEED + i, options={"spec": spec})
done = False
while not done:
obs, r, terminated, truncated, info = env.step(policy.act(obs))
done = terminated or truncated
per_episode.append(info["metrics"])
summary = {
k: {
"mean": statistics.fmean(ep[k] for ep in per_episode),
"std": statistics.pstdev([ep[k] for ep in per_episode]),
}
for k in METRIC_KEYS
}
return {"suite": suite, "episodes": episodes, "metrics": summary}
def load_policy(args, env):
if args.checkpoint:
from train.agent import CheckpointPolicy
return CheckpointPolicy(args.checkpoint)
from baselines.policy import make_policy
return make_policy(args.policy, env, seed=0)
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--policy", default="random", help="oracle | greedy | random")
parser.add_argument("--checkpoint", default=None, help="trained agent checkpoint (.pt)")
parser.add_argument("--suite", default="interp", choices=list(_SUITES))
parser.add_argument("--episodes", type=int, default=100)
parser.add_argument("--gif", default=None, help="also record one episode to this path")
args = parser.parse_args()
env = gym.make("atrium_sim/BrickLayer-v0",
render_mode="rgb_array" if args.gif else None)
policy = load_policy(args, env)
result = evaluate(env, policy, args.suite, args.episodes)
result["policy"] = args.checkpoint or args.policy
if args.gif:
from atrium_sim.render.recorder import record_episode
record_episode(env, policy, args.gif, seed=BASE_SEED)
result["gif"] = args.gif
env.close()
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()