Skip to content
Open
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
8 changes: 3 additions & 5 deletions src/pyrecest/_backend/_shared_numpy/linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,10 @@ def fractional_matrix_power(A, t):

def polar(a, side="right"):
"""Polar decomposition of a square or rectangular matrix."""
signature = (
"(m,n)->(m,n),(m,m)" if side == "left" else "(m,n)->(m,n),(n,n)"
signature = "(m,n)->(m,n),(m,m)" if side == "left" else "(m,n)->(m,n),(n,n)"
return _np.vectorize(_scipy.linalg.polar, signature=signature, excluded=["side"])(
a, side=side
)
return _np.vectorize(
_scipy.linalg.polar, signature=signature, excluded=["side"]
)(a, side=side)


def solve(a, b):
Expand Down
8 changes: 2 additions & 6 deletions src/pyrecest/_backend/pytorch/linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,8 @@ def fractional_matrix_power(A, t):
def polar(a, side="right"):
"""Polar decomposition of a square or rectangular matrix."""
a = _as_linalg_tensor(a)
signature = (
"(m,n)->(m,n),(m,m)" if side == "left" else "(m,n)->(m,n),(n,n)"
)
func = _np.vectorize(
_scipy.linalg.polar, signature=signature, excluded=["side"]
)
signature = "(m,n)->(m,n),(m,m)" if side == "left" else "(m,n)->(m,n),(n,n)"
func = _np.vectorize(_scipy.linalg.polar, signature=signature, excluded=["side"])
unitary, hermitian = func(_as_numpy_no_grad(a), side=side)

return _torch_as_like(unitary, a), _torch_as_like(hermitian, a)
4 changes: 3 additions & 1 deletion src/pyrecest/distributions/abstract_grid_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ def multiply(self, other):
if self.grid_type != other.grid_type:
raise ValueError("Grid types must match before multiplication.")
if (self.grid is None) != (other.grid is None):
raise ValueError("Both grid distributions must either store grids or omit them.")
raise ValueError(
"Both grid distributions must either store grids or omit them."
)
if self.grid is not None and not allclose(self.grid, other.grid):
raise ValueError("Grid coordinates must match before multiplication.")
gd = copy.deepcopy(self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ def pdf(self, za):
"""
za = array(za)
if za.ndim == 0 or za.shape[-1] != self.dim:
raise ValueError(f"za must have trailing dimension {self.dim}, got {za.shape}.")
raise ValueError(
f"za must have trailing dimension {self.dim}, got {za.shape}."
)
single = za.ndim == 1
if single:
za = za.reshape(1, -1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ def pdf(self, za):
"""
za = asarray(za, dtype=complex128)
if za.ndim == 0 or za.shape[-1] != self.dim:
raise ValueError(f"za must have trailing dimension {self.dim}, got {za.shape}.")
raise ValueError(
f"za must have trailing dimension {self.dim}, got {za.shape}."
)
inner = za @ conj(self.mu) # complex inner product, shape (N,) or scalar
return real(exp(self.log_norm_const + self.kappa * abs(inner) ** 2))

Expand Down
13 changes: 3 additions & 10 deletions tests/distributions/test_abstract_grid_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from pyrecest.backend import array
from pyrecest.distributions.abstract_grid_distribution import AbstractGridDistribution


_DEFAULT_GRID = object()


Expand Down Expand Up @@ -62,26 +61,20 @@ def test_multiply_rejects_incompatible_grids(self):

with self.assertRaisesRegex(ValueError, "enforce_pdf_nonnegative"):
dist.multiply(
DummyGridDistribution(
array([1.0, 1.0]), enforce_pdf_nonnegative=False
)
DummyGridDistribution(array([1.0, 1.0]), enforce_pdf_nonnegative=False)
)

with self.assertRaisesRegex(ValueError, "Grid value shapes"):
dist.multiply(DummyGridDistribution(array([[1.0, 1.0]])))

with self.assertRaisesRegex(ValueError, "Grid types"):
dist.multiply(
DummyGridDistribution(
array([1.0, 1.0]), grid_type="cartesian_prod"
)
DummyGridDistribution(array([1.0, 1.0]), grid_type="cartesian_prod")
)

with self.assertRaisesRegex(ValueError, "Grid coordinates"):
dist.multiply(
DummyGridDistribution(
array([1.0, 1.0]), grid=array([[0.0], [2.0]])
)
DummyGridDistribution(array([1.0, 1.0]), grid=array([[0.0], [2.0]]))
)

def test_multiply_combines_compatible_values(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ def test_elevation_helpers_reject_matrix_inputs(self):
z = array([[0.0, 0.0]])

with self.assertRaisesRegex(ValueError, "1-dimensional"):
AbstractSphereSubsetDistribution._sph_to_cart_elevation(
azimuth, elevation
)
AbstractSphereSubsetDistribution._sph_to_cart_elevation(azimuth, elevation)
with self.assertRaisesRegex(ValueError, "1-dimensional"):
AbstractSphereSubsetDistribution._cart_to_sph_elevation(x, y, z)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ def test_constructor_rejects_invalid_shape_or_nonfinite_matrix(self):
]

for C_bad, message in invalid_matrices:
with self.subTest(message=message), self.assertRaisesRegex(ValueError, message):
with self.subTest(message=message), self.assertRaisesRegex(
ValueError, message
):
ComplexAngularCentralGaussianDistribution(C_bad)

def test_constructor_rejects_non_positive_definite_matrix(self):
Expand Down Expand Up @@ -142,7 +144,9 @@ def test_pdf_batch_vs_single(self):
def test_pdf_accepts_list_and_rejects_wrong_dimension(self):
z = [[1.0 + 0j, 0.0 + 0j]]

npt.assert_allclose(self.dist_identity_2d.pdf(z), self.dist_identity_2d.pdf(array(z)))
npt.assert_allclose(
self.dist_identity_2d.pdf(z), self.dist_identity_2d.pdf(array(z))
)

for invalid_z in (1.0 + 0j, [1.0 + 0j], [[1.0 + 0j, 0.0 + 0j, 0.0 + 0j]]):
with self.subTest(invalid_z=invalid_z):
Expand Down
4 changes: 1 addition & 3 deletions tests/distributions/test_complex_watson_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,7 @@ def test_fit_with_weights(self):
self.assertIsInstance(cw_fit, ComplexWatsonDistribution)

def test_estimate_parameters_rejects_invalid_inputs(self):
valid_Z = array(
[[1.0 + 0j, 0.0 + 0j], [0.0 + 0j, 1.0 + 0j]], dtype=complex128
)
valid_Z = array([[1.0 + 0j, 0.0 + 0j], [0.0 + 0j, 1.0 + 0j]], dtype=complex128)
invalid_cases = [
([1.0 + 0j, 0.0 + 0j], None, "two-dimensional"),
(array([[float("nan") + 0j, 0.0 + 0j]], dtype=complex128), None, "finite"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ def test_normalize_rejects_non_numpy_backend(self):
with self.assertRaisesRegex(NotImplementedError, "numpy backend"):
dist.normalize()
finally:
backend.__backend_name__ = original_backend_name # pylint: disable=no-member
backend.__backend_name__ = (
original_backend_name # pylint: disable=no-member
)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,7 @@ def test_plot(self, name, dist, dim):
)

def test_plot_rejects_unsupported_dimension(self):
dist = HypercylindricalDiracDistribution(
1, array([[0.1, 1.0, 2.0, 3.0]])
)
dist = HypercylindricalDiracDistribution(1, array([[0.1, 1.0, 2.0, 3.0]]))

with self.assertRaisesRegex(ValueError, "Plotting"):
dist.plot()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest

import numpy.testing as npt

from pyrecest.backend import array
from pyrecest.distributions.hypersphere_subset.hyperhemispherical_watson_distribution import (
HyperhemisphericalWatsonDistribution,
Expand Down
9 changes: 6 additions & 3 deletions tests/evaluation/test_pareto_objective_validation.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import pandas as pd
import pytest

from pyrecest.evaluation.pareto import is_pareto_front, pareto_front_indices


def test_pareto_front_indices_reject_missing_objective_column():
table = pd.DataFrame({"cost": [1.0, 2.0]})

with pytest.raises(ValueError, match="Pareto objective columns are missing: quality"):
with pytest.raises(
ValueError, match="Pareto objective columns are missing: quality"
):
pareto_front_indices(
table,
["cost", "quality"],
Expand All @@ -18,7 +19,9 @@ def test_pareto_front_indices_reject_missing_objective_column():
def test_is_pareto_front_rejects_missing_objective_column():
table = pd.DataFrame({"cost": [1.0, 2.0]})

with pytest.raises(ValueError, match="Pareto objective columns are missing: quality"):
with pytest.raises(
ValueError, match="Pareto objective columns are missing: quality"
):
is_pareto_front(
table,
["cost", "quality"],
Expand Down
9 changes: 6 additions & 3 deletions tests/filters/test_measurement_reliability_zero_noise.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import numpy as np

from pyrecest.filters.measurement_reliability import normalize_measurement_noise_covariances
from pyrecest.filters.measurement_reliability import (
normalize_measurement_noise_covariances,
)


def _as_covariance_matrix(value, measurement_dim, name):
covariance = np.asarray(value, dtype=float)
if covariance.shape != (measurement_dim, measurement_dim):
raise ValueError(f"{name} must have shape ({measurement_dim}, {measurement_dim})")
raise ValueError(
f"{name} must have shape ({measurement_dim}, {measurement_dim})"
)
return covariance


Expand Down