tests/dynamic/test_carrier.py
from dataclasses import replace
import pytest
import torch
from mcss.dynamic.cache import ObservationCache
from mcss.dynamic.carrier import DynamicSceneCarrier
from mcss.dynamic.config import CarrierConfig
from mcss.dynamic.types import FastWeights, OnlineObservation
from mcss.geometry import make_intrinsics
from mcss.types import Cameras
def _config() -> CarrierConfig:
return CarrierConfig(
feature_dim=4,
hidden_dim=4,
expansion_dim=6,
grid_size=(4, 4, 4),
token_count=16,
)
def _camera(*, backward: bool = False) -> Cameras:
pose = torch.eye(4)
if backward:
pose[0, 0] = -1.0
pose[2, 2] = -1.0
return Cameras(make_intrinsics((8, 8), 170.0), pose, (8, 8))
def _cache(carrier: DynamicSceneCarrier, *, backward: bool = False) -> ObservationCache:
cache = ObservationCache(episode_id="episode-a", scene_id="scene-a")
for frame_id in range(2):
observation = OnlineObservation(
scene_id="scene-a",
frame_id=frame_id,
rgb=torch.full((3, 8, 8), 0.25 + 0.1 * frame_id),
camera=_camera(backward=backward),
)
cache = cache.append(observation, carrier.encode(observation))
return cache
def test_carrier_materializes_finite_typed_scene_and_trace() -> None:
torch.manual_seed(2)
carrier = DynamicSceneCarrier(_config())
cache = _cache(carrier)
fast = carrier.initial_fast(cache.episode_id)
trace = carrier.trace(cache, fast)
state = carrier.materialize(cache, fast)
assert state.density_logits.shape == (1, 1, 4, 4, 4)
assert state.color.shape == (1, 3, 4, 4, 4)
assert state.log_variance.shape == (1, 1, 4, 4, 4)
assert torch.isfinite(state.density_logits).all()
assert torch.isfinite(state.color).all()
assert torch.isfinite(state.log_variance).all()
assert trace.observed_feature_statistics.shape == (16, _config().statistics_dim)
assert trace.fuse_activation.shape == (16, _config().expansion_dim)
assert trace.complete_activation.shape == (16, _config().expansion_dim)
assert trace.candidate_ids.shape == (16,)
assert torch.all((trace.support_weights == 0) | (trace.support_weights == 1))
assert torch.count_nonzero(trace.support_weights) > 0
def test_carrier_backpropagates_to_slow_parameters_and_fast_tensors() -> None:
torch.manual_seed(3)
carrier = DynamicSceneCarrier(_config())
cache = _cache(carrier)
initial = carrier.initial_fast(cache.episode_id)
fast = FastWeights(
episode_id=initial.episode_id,
delta_fuse=torch.zeros_like(initial.delta_fuse, requires_grad=True),
delta_complete=torch.zeros_like(initial.delta_complete, requires_grad=True),
)
state = carrier.materialize(cache, fast)
(state.density_logits.mean() + state.color.mean() + state.log_variance.mean()).backward()
assert fast.delta_fuse.grad is not None
assert fast.delta_complete.grad is not None
assert torch.isfinite(fast.delta_fuse.grad).all()
assert torch.isfinite(fast.delta_complete.grad).all()
assert any(
parameter.grad is not None and torch.isfinite(parameter.grad).all()
for parameter in carrier.parameters()
)
def test_carrier_rejects_fast_weights_from_another_episode() -> None:
carrier = DynamicSceneCarrier(_config())
cache = _cache(carrier)
wrong_episode = carrier.initial_fast("episode-b")
with pytest.raises(ValueError, match="episode"):
carrier.trace(cache, wrong_episode)
with pytest.raises(ValueError, match="episode"):
carrier.materialize(cache, wrong_episode)
def test_each_writable_down_projection_can_change_the_scene_independently() -> None:
torch.manual_seed(4)
carrier = DynamicSceneCarrier(_config())
cache = _cache(carrier)
initial = carrier.initial_fast(cache.episode_id)
fuse_only = replace(initial, delta_fuse=torch.ones_like(initial.delta_fuse))
complete_only = replace(initial, delta_complete=torch.ones_like(initial.delta_complete))
baseline = carrier.materialize(cache, initial)
fused = carrier.materialize(cache, fuse_only)
completed = carrier.materialize(cache, complete_only)
assert carrier.fuse_down.weight.shape == (4, 6)
assert carrier.complete_down.weight.shape == (4, 6)
assert not torch.allclose(fused.density_logits, baseline.density_logits)
assert not torch.allclose(completed.density_logits, baseline.density_logits)
def test_zero_geometric_support_has_zero_write_weight_and_finite_scene() -> None:
carrier = DynamicSceneCarrier(_config())
cache = _cache(carrier, backward=True)
fast = carrier.initial_fast(cache.episode_id)
trace = carrier.trace(cache, fast)
state = carrier.materialize(cache, fast)
assert torch.count_nonzero(trace.support_weights) == 0
assert torch.isfinite(trace.observed_feature_statistics).all()
assert torch.isfinite(state.density_logits).all()
assert torch.isfinite(state.color).all()
assert torch.isfinite(state.log_variance).all()