Skip to content

Commit

Permalink
Revert "Make quad integration measures stateless (#748)"
Browse files Browse the repository at this point in the history
This reverts commit 90b5dd3.
  • Loading branch information
mmahsereci committed Dec 9, 2022
1 parent 90b5dd3 commit 081ba1e
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 94 deletions.
9 changes: 5 additions & 4 deletions src/probnum/quad/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ def as_domain(
"""
if input_dim is not None and input_dim < 1:
raise ValueError(
f"Input dimension must be positive. Current value is ({input_dim})."
f"If given, input dimension must be positive. Current value "
f"is ({input_dim})."
)

if len(domain) != 2:
raise ValueError(f"'domain' must be of length 2 ({len(domain)}).")
raise ValueError(f"domain must be of length 2 ({len(domain)}).")

# Domain limits must have equal dimensions
if np.size(domain[0]) != np.size(domain[1]):
Expand All @@ -84,8 +85,8 @@ def as_domain(
# Size of domain and input dimension do not match
if input_dim != domain_dim:
raise ValueError(
f"If domain limits are not scalars, their lengths "
f"must match the input dimension ({input_dim})."
"If domain limits are not scalars, their lengths "
"must match the input dimension."
)
domain_a = domain[0]
domain_b = domain[1]
Expand Down
4 changes: 2 additions & 2 deletions src/probnum/quad/integration_measures/_integration_measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __call__(self, points: Union[FloatLike, np.ndarray]) -> np.ndarray:
def sample(
self,
n_sample: IntLike,
rng: np.random.Generator,
rng: Optional[np.random.Generator] = np.random.default_rng(),
) -> np.ndarray:
"""Sample ``n_sample`` points from the integration measure.
Expand All @@ -63,7 +63,7 @@ def sample(
n_sample
Number of points to be sampled
rng
A Random number generator.
Random number generator. Optional. Default is `np.random.default_rng()`.
Returns
-------
Expand Down
2 changes: 1 addition & 1 deletion src/probnum/quad/integration_measures/_lebesgue_measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def __call__(self, points: np.ndarray) -> np.ndarray:
def sample(
self,
n_sample: IntLike,
rng: np.random.Generator,
rng: Optional[np.random.Generator] = np.random.default_rng(),
) -> np.ndarray:
return self.random_variable.rvs(
size=(n_sample, self.input_dim), random_state=rng
Expand Down
3 changes: 0 additions & 3 deletions tests/test_quad/test_bq_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@
@pytest.mark.parametrize(
"dom, in_dim",
[
((0, 1), 0), # zero dimension
((0, 1), -2), # negative dimension
((np.zeros(2), np.ones(2)), 3), # length of bounds does not match dimension
((np.zeros(2), np.ones(3)), None), # lower and upper bounds not equal lengths
((np.array([0, 0]), np.array([1, 0])), None), # integration domain is empty
((np.zeros([2, 1]), np.ones([2, 1])), None), # bounds have too many dimensions
((np.zeros([2, 1]), np.ones([2, 1])), 2), # bounds have too many dimensions
((0, 1, 2), 2), # domain has too many elements
((-np.ones(2), np.zeros(2), np.ones(2)), 2), # domain has too many elements
]
)
def test_as_domain_wrong_input(dom, in_dim):
Expand Down
120 changes: 36 additions & 84 deletions tests/test_quad/test_integration_measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,9 @@

from probnum.quad.integration_measures import GaussianMeasure, LebesgueMeasure

# Tests shared by all measures start here


def test_density_call_shape(x, measure):
expected_shape = (x.shape[0],)
assert measure(x).shape == expected_shape


@pytest.mark.parametrize("n_sample", [1, 2, 5])
def test_sample_shape(measure, n_sample, rng):
input_dim = measure.input_dim
res = measure.sample(n_sample=n_sample, rng=rng)
assert res.shape == (n_sample, input_dim)


# Tests for Gaussian measure start here


def test_gaussian_diagonal_covariance(input_dim):
# Tests for Gaussian measure
def test_gaussian_diagonal_covariance(input_dim: int):
"""Check that diagonal covariance matrices are recognised as diagonal."""
mean = np.full((input_dim,), 0.0)
cov = np.eye(input_dim)
Expand Down Expand Up @@ -52,6 +36,13 @@ def test_gaussian_mean_shape_1d(mean, cov):
assert measure.cov.size == 1


@pytest.mark.parametrize("neg_dim", [0, -1, -10, -100])
def test_gaussian_negative_dimension(neg_dim):
"""Make sure that a negative dimension raises ValueError."""
with pytest.raises(ValueError):
GaussianMeasure(0, 1, neg_dim)


def test_gaussian_param_assignment(input_dim: int):
"""Check that diagonal mean and covariance for higher dimensions are extended
correctly."""
Expand All @@ -66,24 +57,15 @@ def test_gaussian_param_assignment(input_dim: int):
assert np.array_equal(measure.cov, np.eye(input_dim))


def test_gaussian_param_assignment_scalar():
def test_gaussian_scalar():
"""Check that the 1d Gaussian case works."""
measure = GaussianMeasure(0.5, 1.5)
assert measure.mean == 0.5
assert measure.cov == 1.5


@pytest.mark.parametrize("wrong_dim", [0, -1, -10, -100])
def test_gaussian_wrong_dimension_raises(wrong_dim):
"""Make sure that a non-positive dimension raises ValueError."""
with pytest.raises(ValueError):
GaussianMeasure(0, 1, wrong_dim)


# Tests for Lebesgue measure start here


def test_lebesgue_input_dim_assignment(input_dim: int):
# Tests for Lebesgue measure
def test_lebesgue_dim_correct(input_dim: int):
"""Check that dimensions are handled correctly."""
domain1 = (0.0, 1.87)
measure11 = LebesgueMeasure(domain=domain1)
Expand All @@ -100,70 +82,40 @@ def test_lebesgue_input_dim_assignment(input_dim: int):
assert measure22.input_dim == input_dim


def test_lebesgue_normalization_value(input_dim: int):
@pytest.mark.parametrize("domain_a", [0, np.full((3,), 0), np.full((13,), 0)])
@pytest.mark.parametrize("domain_b", [np.full((4,), 1.2), np.full((14,), 1.2)])
@pytest.mark.parametrize("input_dim", [-10, -2, 0, 2, 12, 122])
def test_lebesgue_dim_incorrect(domain_a, domain_b, input_dim):
"""Check that ValueError is raised if domain limits have mismatching dimensions or
dimension is not positive."""
with pytest.raises(ValueError):
LebesgueMeasure(domain=(domain_a, domain_b), input_dim=input_dim)


def test_lebesgue_normalization(input_dim: int):
"""Check that normalization constants are handled properly when not equal to one."""
domain = (0, 2)

# normalized
measure = LebesgueMeasure(domain=domain, input_dim=input_dim, normalized=True)

volume = 2**input_dim
assert measure.normalization_constant == 1.0 / volume
assert measure.normalization_constant == 1 / volume


# not normalized
measure = LebesgueMeasure(domain=domain, input_dim=input_dim, normalized=False)
assert measure.normalization_constant == 1.0
@pytest.mark.parametrize("domain", [(0, np.Inf), (-np.Inf, 0), (-np.Inf, np.Inf)])
def test_lebesgue_normalization_raises(domain, input_dim: int):
"""Check that exception is raised when normalization is not possible."""
with pytest.raises(ValueError):
LebesgueMeasure(domain=domain, input_dim=input_dim, normalized=True)


def test_lebesgue_normalization_value_unnormalized(input_dim: int):
def test_lebesgue_unnormalized(input_dim: int):
"""Check that normalization constants are handled properly when equal to one."""
measure1 = LebesgueMeasure(domain=(0, 1), input_dim=input_dim, normalized=True)
measure2 = LebesgueMeasure(domain=(0, 1), input_dim=input_dim, normalized=False)

assert measure1.normalized
assert not measure2.normalized
assert measure1.normalization_constant == measure2.normalization_constant


@pytest.mark.parametrize("wrong_input_dim", [-5, -1, 0])
def test_lebesgue_non_positive_input_dim_raises(wrong_input_dim):
# non positive input dimenions are not allowed
with pytest.raises(ValueError):
LebesgueMeasure(input_dim=wrong_input_dim, domain=(0, 1))


@pytest.mark.parametrize(
"domain",
[
(0.0, np.ones(4)),
(np.ones(4), 0.0),
(np.zeros(4), np.ones(3)),
(np.zeros([4, 1]), np.ones(4)),
(np.zeros(4), np.ones([4, 1])),
(np.zeros([4, 1]), np.ones([4, 1])),
],
)
def test_lebesgue_domain_shape_mismatch_raises(domain):
# left and right bounds of domain are not consistent
with pytest.raises(ValueError):
LebesgueMeasure(domain=domain)


@pytest.mark.parametrize(
"input_dim,domain",
[
(1, (np.zeros(3), np.ones(3))),
(2, (np.zeros(3), np.ones(3))),
(5, (np.zeros(3), np.ones(3))),
],
)
def test_lebesgue_domain_input_dim_mismatch_raises(input_dim, domain):
# input dimension does not agree with domain shapes
with pytest.raises(ValueError):
LebesgueMeasure(input_dim=input_dim, domain=domain)


@pytest.mark.parametrize("domain", [(0, np.Inf), (-np.Inf, 0), (-np.Inf, np.Inf)])
def test_lebesgue_normalization_raises(domain, input_dim: int):
"""Check that exception is raised when normalization is not possible."""
with pytest.raises(ValueError):
LebesgueMeasure(domain=domain, input_dim=input_dim, normalized=True)
# Tests for all integration measures
def test_density_call(x, measure):
expected_shape = (x.shape[0],)
assert measure(x).shape == expected_shape

0 comments on commit 081ba1e

Please sign in to comment.