Source code for scimba_torch.integration.monte_carlo_time

"""A uniform time sampler for Monte Carlo methods."""

from typing import Any, Sequence

import torch

from scimba_torch.utils.scimba_tensors import LabelTensor

TIME_TYPE = int | float


def _is_time_type(arg: Any) -> bool:
    return isinstance(arg, int) or isinstance(arg, float)


[docs] class UniformTimeSampler: """A class used to sample uniformly distributed time points within a given bound. Args: bound: A tuple representing the lower and upper bounds for sampling. Raises: TypeError: If time interval is not a Sequence of two int or float. ValueError: If lower bound is greater than upper bound. """ def __init__(self, bound: tuple[float, float]): if not ( isinstance(bound, Sequence) and (len(bound) == 2) and all(_is_time_type(b) for b in bound) ): raise TypeError("time interval must be a Sequence of two int or float") self.bound = ( float(bound[0]), float(bound[1]), ) #: A tuple representing the lower and upper bounds for sampling. if self.bound[0] > self.bound[1]: raise ValueError( "can not create a time sampler for empty time interval [%f, %f]" % (self.bound[0], self.bound[1]) )
[docs] def sample(self, n: int) -> LabelTensor: """Generate a sample of random numbers within the specified bounds. Args: n: The number of samples to generate. Returns: A tensor containing the generated samples and corresponding labels. Raises: TypeError: If argument is not an integer. ValueError: If argument is negative. """ if not isinstance(n, int): raise TypeError("argument to sample method must be an integer") if n < 0: raise ValueError("argument to sample method must be non-negative") samples = torch.rand(n, 1) samples[:, 0] = samples[:, 0] * (self.bound[1] - self.bound[0]) + self.bound[0] samples.requires_grad_() labels = torch.zeros(n, dtype=torch.int32) data = LabelTensor(samples, labels) return data