Skip to content

Commit 7bae4a3

Browse files
committed
better coverage
1 parent d9419f9 commit 7bae4a3

3 files changed

Lines changed: 34 additions & 5 deletions

File tree

ot/solvers/_linear.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,13 +490,13 @@ def solve(
490490
else:
491491
# stabilize kl of 0 mass
492492
if nx.any(a == 0) or nx.any(b == 0):
493-
a = a + 1e-16 * nx.min(a)
494-
b = b + 1e-16 * nx.min(b)
493+
a = a + 1e-15 * nx.min(a)
494+
b = b + 1e-15 * nx.min(b)
495495
print(
496496
"Warning: a or b has 0 mass, adding small mass to avoid NaN in KL divergence."
497497
)
498498
value = value_linear + reg * nx.kl_div(
499-
plan, a[:, None] * b[None, :]
499+
plan, a[:, None] * b[None, :] + 1e-15
500500
)
501501

502502
if grad == "envelope": # set the gradient at convergence

test/test_solvers.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@
3333
{"method": "gaussian"},
3434
{"method": "gaussian", "reg": 1},
3535
{"method": "gaussian_hd", "rank": 1},
36+
{"method": "gaussian_hd", "rank": 3},
3637
{"method": "factored", "rank": 2},
3738
{"method": "lowrank", "rank": 2, "max_iter": 5},
3839
{"method": "nystroem", "rank": 2},
3940
{"method": "sliced", "n_projections": 10},
41+
{"method": "sliced", "n_projections": 10, "metric": "euclidean"},
4042
{"method": "max_sliced", "n_projections": 10},
43+
{"method": "max_sliced", "n_projections": 10, "metric": "euclidean"},
4144
]
4245

4346
lst_parameters_solve_sample_NotImplemented = [
@@ -808,6 +811,32 @@ def test_solve_sample_methods(nx, method_params):
808811
np.testing.assert_allclose(sol2.value, 0, atol=1e-10)
809812

810813

814+
def test_zero_mass_solvers():
815+
# test that solvers handle zero mass distributions correctly
816+
n_samples_s = 10
817+
n_samples_t = 9
818+
n_features = 2
819+
rng = np.random.RandomState(42)
820+
821+
x = rng.randn(n_samples_s, n_features)
822+
y = rng.randn(n_samples_t, n_features)
823+
a = ot.utils.unif(n_samples_s)
824+
b = ot.utils.unif(n_samples_t)
825+
826+
# Set one of the distributions to zero mass
827+
a[0] = 0.0
828+
b[0] = 0.0
829+
830+
a /= a.sum()
831+
b /= b.sum()
832+
833+
res = ot.solve_sample(x, y, a, b)
834+
res_reg = ot.solve_sample(x, y, a, b, reg=1.0)
835+
836+
assert np.isnan(res.value) == False
837+
assert np.isnan(res_reg.value) == False
838+
839+
811840
@pytest.skip_backend("tf", reason="Not implemented for tf backend")
812841
@pytest.mark.parametrize("debias", [True, False, "split"])
813842
@pytest.mark.parametrize("reg", [None, 10])

test/test_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ def test_split_sample_ratio(nx, ratio, n, random):
975975

976976
# test uniform weights
977977
X1, X2, a1, a2, id1, id2 = ot.utils.split_sample_ratio(
978-
X, ratio=ratio, random_state=seed, nx=nx
978+
X, ratio=ratio, random_split=random, random_state=seed, nx=nx
979979
)
980980

981981
np.testing.assert_allclose(nx.to_numpy(a1).sum(), ratio, atol=1e-5)
@@ -986,7 +986,7 @@ def test_split_sample_ratio(nx, ratio, n, random):
986986

987987
# test non uniform weights
988988
X1, X2, a1, a2, id1, id2 = ot.utils.split_sample_ratio(
989-
X, ratio=ratio, a=a, random_state=seed
989+
X, ratio=ratio, a=a, random_split=random, random_state=seed
990990
)
991991

992992
with pytest.raises(ValueError):

0 commit comments

Comments
 (0)