from pathlib import Path import numpy as np import torch from minidreamer.data.replay_buffer import ReplayBuffer def make_episode(length: int, reward: float = 0.0): obs = np.random.rand(length + 1, 64, 64, 3).astype(np.float32) actions = np.arange(length, dtype=np.int64) % 7 rewards = np.full(length, reward, dtype=np.float32) terminated = np.zeros(length, dtype=np.float32) truncated = np.zeros(length, dtype=np.float32) done = np.zeros(length, dtype=np.float32) terminated[-1] = 1.0 done[-1] = 1.0 return obs, actions, rewards, terminated, truncated, done def test_replay_buffer_sampling_and_padding(tmp_path: Path): buffer = ReplayBuffer(capacity_episodes=10, sequence_length=8, batch_size=4) for episode_id, length in enumerate((3, 5, 9)): obs, actions, rewards, terminated, truncated, done = make_episode(length, reward=float(episode_id)) buffer.add_episode(obs, actions, rewards, terminated, truncated, done, episode_id=episode_id) available_split = next(split for split in ("train", "val", "test") if buffer.episode_ids(split)) batch = buffer.sample_sequences(split=available_split, batch_size=2, rng=np.random.default_rng(0)) assert batch["obs"].shape == (2, 9, 64, 64, 3) assert batch["actions"].shape == (2, 8) assert batch["mask"].shape == (2, 8) assert np.all(batch["mask"].sum(axis=1) >= 1) save_dir = tmp_path / "replay" buffer.save(save_dir) loaded = ReplayBuffer.load(save_dir) assert loaded.summary()["episodes"] == buffer.summary()["episodes"] assert loaded.summary()["env_steps"] == buffer.summary()["env_steps"] def test_replay_buffer_torch_batch_shapes(): buffer = ReplayBuffer(capacity_episodes=4, sequence_length=4, batch_size=2) obs, actions, rewards, terminated, truncated, done = make_episode(5, reward=1.0) buffer.add_episode(obs, actions, rewards, terminated, truncated, done) available_split = next(split for split in ("train", "val", "test") if buffer.episode_ids(split)) batch = buffer.sample_sequences(split=available_split, batch_size=2, rng=np.random.default_rng(1)) tensor_batch = ReplayBuffer.batch_to_torch(batch) assert tensor_batch["obs"].shape == (2, 5, 3, 64, 64) assert tensor_batch["actions"].dtype == torch.int64