Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/pyrecest/tracking/nonparametric_cardinality.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,19 @@

from dataclasses import dataclass
from math import exp, isfinite, lgamma, log
from numbers import Integral
from numbers import Integral, Real
from typing import Sequence


def _as_finite_real_scalar(value, name: str) -> float:
if isinstance(value, bool) or not isinstance(value, Real):
raise TypeError(f"{name} must be a real scalar.")
value = float(value)
if not isfinite(value):
raise ValueError(f"{name} must be finite.")
return value


@dataclass(frozen=True)
class PitmanYorCardinalityPrior:
"""Pitman--Yor Chinese-restaurant prior over target-generated clusters.
Expand Down Expand Up @@ -48,12 +57,8 @@ class PitmanYorCardinalityPrior:
discount: float = 0.0

def __post_init__(self) -> None:
strength = float(self.strength)
discount = float(self.discount)
if not isfinite(strength):
raise ValueError("strength must be finite.")
if not isfinite(discount):
raise ValueError("discount must be finite.")
strength = _as_finite_real_scalar(self.strength, "strength")
discount = _as_finite_real_scalar(self.discount, "discount")
if not 0.0 <= discount < 1.0:
raise ValueError("discount must satisfy 0 <= discount < 1.")
if strength <= -discount:
Expand Down
15 changes: 15 additions & 0 deletions tests/tracking/test_nonparametric_cardinality.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import math

import numpy as np
import pytest

from pyrecest.tracking.nonparametric_cardinality import (
Expand Down Expand Up @@ -81,6 +82,20 @@ def test_parameter_validation():
DirichletProcessCardinalityPrior(strength=0.0)


@pytest.mark.parametrize(
"kwargs",
[
pytest.param({"strength": True}, id="python-bool-strength"),
pytest.param({"strength": np.bool_(True)}, id="numpy-bool-strength"),
pytest.param({"discount": False}, id="python-bool-discount"),
pytest.param({"discount": np.bool_(False)}, id="numpy-bool-discount"),
],
)
def test_parameter_validation_rejects_boolean_scalars(kwargs):
with pytest.raises(TypeError, match="must be a real scalar"):
PitmanYorCardinalityPrior(**kwargs)


def test_cluster_size_validation():
prior = PitmanYorCardinalityPrior()

Expand Down
Loading