Source code for spflow.meta.data.interval_evidence

"""Interval evidence container for range inference.

Allows passing interval bounds (low, high) to log_likelihood instead of point values.
"""

from __future__ import annotations

from dataclasses import dataclass

import torch
from torch import Tensor


[docs] @dataclass class IntervalEvidence: """Represents interval bounds for range inference queries. Use this instead of a point evidence tensor when computing P(low <= X <= high). Attributes: low: Lower bounds tensor of shape (batch, features). Use NaN for no lower bound. high: Upper bounds tensor of shape (batch, features). Use NaN for no upper bound. Example: >>> import torch >>> evidence = IntervalEvidence( ... low=torch.tensor([[0.2, 0.3]]), ... high=torch.tensor([[0.8, 0.7]]) ... ) >>> evidence.shape torch.Size([1, 2]) """ low: Tensor high: Tensor def __post_init__(self) -> None: """Validate interval bounds after initialization.""" if self.low.shape != self.high.shape: raise ValueError(f"low and high must have same shape, got {self.low.shape} and {self.high.shape}") if self.low.dim() != 2: raise ValueError(f"Tensors must be 2-dimensional (batch, features), got {self.low.dim()}D") # Check low <= high for finite entries finite_mask = torch.isfinite(self.low) & torch.isfinite(self.high) if (self.low[finite_mask] > self.high[finite_mask]).any(): raise ValueError("Invalid interval: low > high for some entries") @property def shape(self) -> torch.Size: """Return shape of the evidence tensors.""" return self.low.shape @property def device(self) -> torch.device: """Return device of the evidence tensors.""" return self.low.device
[docs] def to(self, device: torch.device) -> "IntervalEvidence": """Move evidence to specified device.""" return IntervalEvidence(low=self.low.to(device), high=self.high.to(device))