게시판문랜딩 프로그램으로 이해하는 강화학습예제 소스

예제 소스

문랜딩 프로그램으로 이해하는 강화학습 · 파일 6개

smoke_test.py

"""환경/에이전트 기본 동작 점검용 스크립트.

torch + pygame 까지 설치된 상태에서 다음을 검증한다:

1. MoonLanderEnv reset/step 이 정상 동작하고 상태/관측 차원이 맞는지.
2. 모든 분사기 ON/OFF 행동을 수행해도 NaN 이 발생하지 않는지.
3. 무동작 시 자유낙하로 종료(추락)되는지.
4. DQNAgent 가 학습 1 step 을 무사히 수행하는지.

사용:
    python smoke_test.py
"""

from __future__ import annotations

import math
import sys

import numpy as np


def test_env_basic() -> None:
    from lander_env import MoonLanderEnv
    env = MoonLanderEnv(seed=0)
    obs = env.reset()
    assert obs.shape == (env.STATE_DIM,), obs.shape
    assert np.all(np.isfinite(obs))

    # 무동작 → 자유낙하로 추락
    total = 0.0
    for _ in range(env.MAX_STEPS + 1):
        obs, r, done, info = env.step(0)
        total += r
        assert np.all(np.isfinite(obs))
        if done:
            break
    assert info.result in ("crashed", "out_of_bounds", "timeout"), info.result
    print(f"[ok] free-fall episode -> {info.result}, reward={total:.1f}")


def test_env_actions() -> None:
    from lander_env import MoonLanderEnv
    env = MoonLanderEnv(seed=1)
    for action in range(env.NUM_ACTIONS):
        env.reset()
        for _ in range(50):
            obs, r, done, info = env.step(action)
            if done:
                break
        assert np.all(np.isfinite(obs))
    print(f"[ok] all {env.NUM_ACTIONS} actions stable")


def test_main_engine_lifts() -> None:
    """메인 엔진만 켜면 적어도 짧은 시간 동안은 위로 가속해야 한다."""
    from lander_env import MoonLanderEnv
    env = MoonLanderEnv(seed=2, randomize=False)
    env.reset()
    vy0 = env.state.vy
    for _ in range(10):
        env.step(1)  # bit 0 = main engine
    assert env.state.vy > vy0, "main engine should produce upward acceleration"
    print(f"[ok] main engine lifts: vy {vy0:.2f} -> {env.state.vy:.2f}")


def test_dqn_one_step() -> None:
    from lander_env import MoonLanderEnv
    from dqn_agent import DQNAgent, DQNConfig

    env = MoonLanderEnv(seed=3)
    cfg = DQNConfig(buffer_size=2_000, learn_start=100, batch_size=32)
    agent = DQNAgent(cfg)

    # transition 채우기
    obs = env.reset()
    for _ in range(200):
        a = agent.act(obs)
        ns, r, d, info = env.step(a)
        agent.remember(obs, a, r, ns, d)
        obs = env.reset() if d else ns

    loss = agent.learn()
    assert loss is not None and math.isfinite(loss), loss
    print(f"[ok] dqn learn step: loss={loss:.4f}, device={agent.device}")


def main() -> int:
    test_env_basic()
    test_env_actions()
    test_main_engine_lifts()
    test_dqn_one_step()
    print("\nall smoke tests passed.")
    return 0


if __name__ == "__main__":
    sys.exit(main())