Source: tests/dynamic/test_policy.py · Plain text

tests/dynamic/test_policy.py

import torch

from mcss.dynamic.policy import (
    ACTION_ORDER,
    FEATURE_SCHEMA_VERSION,
    POLICY_FEATURE_DIM,
    LearnedActionPolicy,
    control_to_features,
)
from mcss.dynamic.types import Action, ControlInput


def _control(**updates):
    values = {
        "rgb_mse": 0.1,
        "opacity_mean": 0.2,
        "current_image_mean": 0.3,
        "density_mean": 0.4,
        "fast_norm": 0.5,
        "observed_count": 2,
        "previous_action": Action.OFF,
        "remaining_budget": 100.0,
        "image_feature_stats": (0.1, 0.2, -0.3, 0.4),
        "rgb_residual_4x4": tuple(float(index) / 100 for index in range(48)),
        "coverage": 0.7,
        "valid_count": 12,
        "camera_change": (0.1, 0.2, 0.0, 0.0, 0.0, 0.01),
        "fast_state_stats": (0.1, 0.2, 0.3, 0.04),
        "remaining_steps": 3,
    }
    values.update(updates)
    return ControlInput(**values)


def test_feature_schema_is_fixed_finite_and_prefix_only():
    control = _control()
    features = control_to_features(control)

    assert FEATURE_SCHEMA_VERSION == "mcss.dynamic.policy_features.v1"
    assert features.shape == (POLICY_FEATURE_DIM,)
    assert features.dtype == torch.float32
    assert torch.isfinite(features).all()
    assert control_to_features(control).equal(features)


def test_legacy_control_constructor_keeps_deterministic_optional_defaults():
    control = ControlInput(0.1, 0.2, 0.3, 0.4, 0.5, 2, Action.OFF, 100.0)
    features = control_to_features(control)

    assert features.shape == (POLICY_FEATURE_DIM,)
    assert torch.isfinite(features).all()


def test_learned_policy_masks_infeasible_actions_and_prefers_off_on_ties():
    policy = LearnedActionPolicy(hidden_dim=8, seed=3)
    with torch.no_grad():
        for parameter in policy.parameters():
            parameter.zero_()

    control = _control()
    assert policy.choose(control, ACTION_ORDER) is Action.OFF
    assert policy.choose(control, (Action.FUSE, Action.COMPLETE, Action.ALL)) is Action.FUSE
    assert policy.choose(control, (Action.ALL,)) is Action.ALL


def test_policy_rejects_nonfinite_features_and_negative_budget():
    policy = LearnedActionPolicy(hidden_dim=8, seed=3)
    with torch.no_grad():
        bad = _control(rgb_residual_4x4=tuple([float("nan")] + [0.0] * 47))
    try:
        control_to_features(bad)
    except ValueError as error:
        assert "finite" in str(error)
    else:
        raise AssertionError("nonfinite feature summary was accepted")

    try:
        _control(remaining_budget=-1.0)
    except ValueError as error:
        assert "remaining_budget" in str(error)
    else:
        raise AssertionError("negative remaining budget was accepted")

    assert policy.declared_work_units > 1