"""Simple and efficient dataset implementations for Kaira.
This module provides dataset classes for communication systems and information theory experiments.
All datasets generate data on-demand for memory efficiency and support PyTorch DataLoader.
"""
from typing import Callable, Optional, Tuple, Union
import numpy as np
import torch
from torch.utils.data import Dataset
[docs]
class BinaryDataset(Dataset):
"""Dataset for binary tensor data with configurable probability.
Generates binary tensors on-demand with specified probability of 1s. Useful for digital
communication and coding theory experiments.
"""
[docs]
def __init__(
self,
length: int,
shape: Union[int, Tuple[int, ...]] = (128,),
prob: float = 0.5,
seed: Optional[int] = None,
):
"""Initialize the binary dataset.
Args:
length: Number of samples in the dataset
shape: Shape of each tensor (int for 1D, tuple for multi-dimensional)
prob: Probability of generating 1s (default: 0.5)
seed: Random seed for reproducibility
"""
self.length = length
self.shape = (shape,) if isinstance(shape, int) else tuple(shape)
self.prob = prob
self.rng = np.random.RandomState(seed)
def __len__(self) -> int:
"""Return the size of the dataset."""
return self.length
def __getitem__(self, idx: int) -> torch.Tensor:
"""Generate a binary tensor sample.
Args:
idx: Index of the sample (used for deterministic generation)
Returns:
Binary tensor with values 0 or 1
"""
# Use index as additional seed for deterministic generation
local_rng = np.random.RandomState(self.rng.randint(0, 2**31) + idx)
data = local_rng.binomial(1, self.prob, size=self.shape).astype(np.float32)
return torch.from_numpy(data)
[docs]
class GaussianDataset(Dataset):
"""Dataset for Gaussian distributed tensor data.
Generates tensors with Gaussian distributed random values on-demand. Useful for noise modeling
and channel simulation.
"""
[docs]
def __init__(
self,
length: int,
shape: Union[int, Tuple[int, ...]] = (128,),
mean: float = 0.0,
std: float = 1.0,
seed: Optional[int] = None,
):
"""Initialize the Gaussian dataset.
Args:
length: Number of samples in the dataset
shape: Shape of each tensor (int for 1D, tuple for multi-dimensional)
mean: Mean of the Gaussian distribution
std: Standard deviation of the Gaussian distribution
seed: Random seed for reproducibility
"""
self.length = length
self.shape = (shape,) if isinstance(shape, int) else tuple(shape)
self.mean = mean
self.std = std
self.rng = np.random.RandomState(seed)
def __len__(self) -> int:
"""Return the size of the dataset."""
return self.length
def __getitem__(self, idx: int) -> torch.Tensor:
"""Generate a Gaussian tensor sample.
Args:
idx: Index of the sample (used for deterministic generation)
Returns:
Tensor with Gaussian distributed values
"""
# Use index as additional seed for deterministic generation
local_rng = np.random.RandomState(self.rng.randint(0, 2**31) + idx)
data = local_rng.normal(self.mean, self.std, size=self.shape).astype(np.float32)
return torch.from_numpy(data)
[docs]
class FunctionDataset(Dataset):
"""Dataset that applies a custom function to generate data.
Flexible dataset for custom data generation using user-provided functions. Useful for complex
signal generation and custom experiments.
"""
[docs]
def __init__(
self,
length: int,
generator_fn: Callable[[int], torch.Tensor],
seed: Optional[int] = None,
):
"""Initialize the function dataset.
Args:
length: Number of samples in the dataset
generator_fn: Function that takes an index and returns a tensor
seed: Random seed for reproducibility
"""
self.length = length
self.generator_fn = generator_fn
if seed is not None:
torch.manual_seed(seed)
np.random.seed(seed)
def __len__(self) -> int:
"""Return the size of the dataset."""
return self.length
def __getitem__(self, idx: int) -> torch.Tensor:
"""Generate data using the custom function.
Args:
idx: Index of the sample
Returns:
Tensor generated by the custom function
"""
return self.generator_fn(idx)
__all__ = [
"BinaryDataset",
"UniformDataset",
"GaussianDataset",
"CorrelatedDataset",
"FunctionDataset",
]