Skip to content

Samples

Construct LandscapeSample(x, y, lower, upper, sense="minimize") from paired finite observations. x has shape (n, d), y has shape (n,), and both bounds have shape (d,). The bounds are inclusive and each lower bound must be strictly below its upper bound.

Arrays are copied into read-only float64 storage. Computation checks that exposed arrays have not been modified since construction. Read samples and objective sense for the integrity and maximization conventions.

LandscapeSample dataclass

Paired decision and objective observations with explicit box bounds.

Source code in src/orivex/sample.py
@dataclass(frozen=True, slots=True, init=False)
class LandscapeSample:
    """Paired decision and objective observations with explicit box bounds."""

    x: FloatArray
    y: FloatArray
    lower: FloatArray
    upper: FloatArray
    sense: ObjectiveSense
    _minimization_y: FloatArray
    _fingerprint: str
    _integrity: str

    def __init__(
        self,
        x: npt.ArrayLike,
        y: npt.ArrayLike,
        lower: npt.ArrayLike,
        upper: npt.ArrayLike,
        sense: ObjectiveSense | ObjectiveSenseName = ObjectiveSense.MINIMIZE,
    ) -> None:
        x_array = _readonly_float_array(x, dimensions=2, name="X")
        y_array = _readonly_float_array(y, dimensions=1, name="y")
        lower_array = _readonly_float_array(lower, dimensions=1, name="lower")
        upper_array = _readonly_float_array(upper, dimensions=1, name="upper")
        sense_value = ObjectiveSense(sense)

        observations, dimension = x_array.shape
        if observations == 0 or dimension == 0:
            raise ValueError("X must contain at least one observation and one variable")
        if y_array.shape != (observations,):
            raise ValueError(f"y must have shape ({observations},), got {y_array.shape}")
        if lower_array.shape != (dimension,) or upper_array.shape != (dimension,):
            raise ValueError(f"bounds must both have shape ({dimension},)")
        if not np.all(lower_array < upper_array):
            raise ValueError("every lower bound must be strictly smaller than its upper bound")
        if np.any(x_array < lower_array) or np.any(x_array > upper_array):
            raise ValueError("all observations must lie within the inclusive box bounds")

        object.__setattr__(self, "x", x_array)
        object.__setattr__(self, "y", y_array)
        object.__setattr__(self, "lower", lower_array)
        object.__setattr__(self, "upper", upper_array)
        object.__setattr__(self, "sense", sense_value)

        minimization_y = y_array if sense_value is ObjectiveSense.MINIMIZE else -y_array
        minimization_y.flags.writeable = False
        object.__setattr__(self, "_minimization_y", minimization_y)

        inputs = (x_array, y_array, lower_array, upper_array)
        object.__setattr__(self, "_fingerprint", _content_digest(inputs, sense_value))
        object.__setattr__(
            self, "_integrity", _content_digest((*inputs, minimization_y), sense_value)
        )

    @property
    def n_observations(self) -> int:
        return self.x.shape[0]

    @property
    def dimension(self) -> int:
        return self.x.shape[1]

    @property
    def minimization_y(self) -> FloatArray:
        """Objective observations transformed to minimization convention."""

        return self._minimization_y

    @property
    def fingerprint(self) -> str:
        """Stable checksum of numerical inputs and objective sense."""

        return self._fingerprint

    def validate_unchanged(self) -> None:
        """Detect in-place mutation of the exposed arrays since construction.

        The arrays are handed out read-only, but callers can re-enable the
        ``writeable`` flag on the owning storage (or reach it through an alias)
        and mutate the values in place. That would leave :attr:`fingerprint`
        stale, breaking the provenance / cache-key contract, so mutation is
        detected here before the sample is consumed.
        """

        current = _content_digest(
            (self.x, self.y, self.lower, self.upper, self._minimization_y), self.sense
        )
        if current != self._integrity:
            raise RuntimeError("LandscapeSample arrays must not be modified in place")

x instance-attribute

x: FloatArray

y instance-attribute

y: FloatArray

lower instance-attribute

lower: FloatArray

upper instance-attribute

upper: FloatArray

sense instance-attribute

sense: ObjectiveSense

n_observations property

n_observations: int

dimension property

dimension: int

minimization_y property

minimization_y: FloatArray

Objective observations transformed to minimization convention.

fingerprint property

fingerprint: str

Stable checksum of numerical inputs and objective sense.

__init__

__init__(
    x: ArrayLike,
    y: ArrayLike,
    lower: ArrayLike,
    upper: ArrayLike,
    sense: ObjectiveSense
    | ObjectiveSenseName = ObjectiveSense.MINIMIZE,
) -> None
Source code in src/orivex/sample.py
def __init__(
    self,
    x: npt.ArrayLike,
    y: npt.ArrayLike,
    lower: npt.ArrayLike,
    upper: npt.ArrayLike,
    sense: ObjectiveSense | ObjectiveSenseName = ObjectiveSense.MINIMIZE,
) -> None:
    x_array = _readonly_float_array(x, dimensions=2, name="X")
    y_array = _readonly_float_array(y, dimensions=1, name="y")
    lower_array = _readonly_float_array(lower, dimensions=1, name="lower")
    upper_array = _readonly_float_array(upper, dimensions=1, name="upper")
    sense_value = ObjectiveSense(sense)

    observations, dimension = x_array.shape
    if observations == 0 or dimension == 0:
        raise ValueError("X must contain at least one observation and one variable")
    if y_array.shape != (observations,):
        raise ValueError(f"y must have shape ({observations},), got {y_array.shape}")
    if lower_array.shape != (dimension,) or upper_array.shape != (dimension,):
        raise ValueError(f"bounds must both have shape ({dimension},)")
    if not np.all(lower_array < upper_array):
        raise ValueError("every lower bound must be strictly smaller than its upper bound")
    if np.any(x_array < lower_array) or np.any(x_array > upper_array):
        raise ValueError("all observations must lie within the inclusive box bounds")

    object.__setattr__(self, "x", x_array)
    object.__setattr__(self, "y", y_array)
    object.__setattr__(self, "lower", lower_array)
    object.__setattr__(self, "upper", upper_array)
    object.__setattr__(self, "sense", sense_value)

    minimization_y = y_array if sense_value is ObjectiveSense.MINIMIZE else -y_array
    minimization_y.flags.writeable = False
    object.__setattr__(self, "_minimization_y", minimization_y)

    inputs = (x_array, y_array, lower_array, upper_array)
    object.__setattr__(self, "_fingerprint", _content_digest(inputs, sense_value))
    object.__setattr__(
        self, "_integrity", _content_digest((*inputs, minimization_y), sense_value)
    )

validate_unchanged

validate_unchanged() -> None

Detect in-place mutation of the exposed arrays since construction.

The arrays are handed out read-only, but callers can re-enable the writeable flag on the owning storage (or reach it through an alias) and mutate the values in place. That would leave :attr:fingerprint stale, breaking the provenance / cache-key contract, so mutation is detected here before the sample is consumed.

Source code in src/orivex/sample.py
def validate_unchanged(self) -> None:
    """Detect in-place mutation of the exposed arrays since construction.

    The arrays are handed out read-only, but callers can re-enable the
    ``writeable`` flag on the owning storage (or reach it through an alias)
    and mutate the values in place. That would leave :attr:`fingerprint`
    stale, breaking the provenance / cache-key contract, so mutation is
    detected here before the sample is consumed.
    """

    current = _content_digest(
        (self.x, self.y, self.lower, self.upper, self._minimization_y), self.sense
    )
    if current != self._integrity:
        raise RuntimeError("LandscapeSample arrays must not be modified in place")

ObjectiveSense

Bases: str, Enum

Source code in src/orivex/sample.py
class ObjectiveSense(str, Enum):
    MINIMIZE = "minimize"
    MAXIMIZE = "maximize"

MINIMIZE class-attribute instance-attribute

MINIMIZE = 'minimize'

MAXIMIZE class-attribute instance-attribute

MAXIMIZE = 'maximize'

ObjectiveSenseName module-attribute

ObjectiveSenseName: TypeAlias = Literal[
    "minimize", "maximize"
]