Skip to content

Commit b734901

Browse files
authored
Merge branch 'master' into tree
2 parents f81fa30 + 44fd091 commit b734901

6 files changed

Lines changed: 782 additions & 3 deletions

File tree

CITATION.cff

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ authors:
8181
- given-names: David
8282
family-names: Coeurjolly
8383
affiliation: CNRS, LIRIS
84+
- given-names: Marco
85+
family-names: Corneli
86+
affiliation: Université Côte d'Azur
8487

8588
identifiers:
8689
- type: url

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,3 +464,7 @@ Artificial Intelligence.
464464
[86] Tanguy, E., Chapel, L., Delon, J. (2025). [Sliced Transport Plans](https://arxiv.org/abs/2508.01243) arXiv preprint 2506.03661.
465465

466466
[87] Liu, X., Diaz Martin, R., Bai Y., Shahbazi A., Thorpe M., Aldroubi A., Kolouri, S. (2024). [Expected Sliced Transport Plans](https://openreview.net/forum?id=P7O1Vt1BdU). International Conference on Learning Representations.
467+
468+
[88] Bouveyron, C. & Corneli, M. (2026). [Scaling optimal transport to high-dimensional Gaussian distributions with application to domain adaptation](https://hal.science/hal-04930868v4/file/Article-OT-HDGauss-v4.pdf). Statistics and Computing 36.2 (2026): 88.
469+
470+
[89] Tipping, M.E. & Bishop, C.M. (1999). [Probabilistic principal component analysis]. Journal of the Royal Statistical Society Series B: Statistical Methodology 61.3 (1999): 611-622.

RELEASES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ This new release adds support for sparse cost matrices and a new lazy EMD solver
2929
- Add a numerically stable log-domain solver for entropic partial Wasserstein, selectable via the new `method` parameter of `entropic_partial_wasserstein` (`method='sinkhorn_log'`) or directly through `entropic_partial_wasserstein_logscale` (Issue #723)
3030
- Add cost functions between linear operators following [A Spectral-Grassmann Wasserstein metric for operator representations of dynamical systems](https://arxiv.org/pdf/2509.24920), implemented in `ot.sgot` (PR #792)
3131
- Build wheels on ubuntu ARM to avoid QEMU emulation (PR #818)
32+
- Add new methods to compute the linear transport map and the related 2-Wasserstein distance betweeen high-dimensional (HD) Gaussian distributions as described in [88], implemented in `ot.gaussian.bures_wasserstein_mapping_hd` and `ot.gaussian.bures_wasserstein_distance_hd`, respectively. Two additional methods estimate the same quantities from the source and destination observed data and are implemented in `ot.gaussian.empirical_bures_wasserstein_mapping_hd` and `ot.gaussian.empirical_bures_wasserstein_distance_hd`, respectively (PR #814)
33+
3234

3335
#### Closed issues
3436

ot/datasets.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import numpy as np
1010
import scipy as sp
11+
from scipy.stats import ortho_group, multivariate_normal
1112
from .utils import check_random_state, deprecated
1213

1314

@@ -180,3 +181,97 @@ def make_data_classif(dataset, n, nz=0.5, theta=0, p=0.5, random_state=None, **k
180181
def get_data_classif(dataset, n, nz=0.5, theta=0, random_state=None, **kwargs):
181182
"""Deprecated see make_data_classif"""
182183
return make_data_classif(dataset, n, nz=0.5, theta=0, random_state=None, **kwargs)
184+
185+
186+
def make_gauss_hd(
187+
ns, nt, p=100, dim=5, m_diff=3.0, a=(10.0, 15.0), b=(3.0, 3.0), sub_the_same=False
188+
):
189+
"""Generation of source and target domains from Gaussian HD distributions
190+
191+
Parameters
192+
----------
193+
ns : int
194+
number of samples (source)
195+
nt : int
196+
number of samples (target)
197+
p : int
198+
dimension of the ambient space the data live in
199+
dim : (int,int) or int
200+
the intrinsic dimensions of the source and target Gaussian HD distriutions. If a single int the intrinsic dimension is assumed to be the same
201+
m_diff : float
202+
the shift in the first coordinate of the means of the Gaussian HD distributions, i.e. ms_0 and mt_0, respectively (see code)
203+
a : (float, float)
204+
positive floating numbers corresponding to the isotropic variances in the principal subspace, for the source and target distributions, respectively. The same as \delta in :ref:`[1] <references-make_gauss-hd>`, Proposition 2.2
205+
b : (float, float)
206+
positive floating numbers corresponding to the isotropic variance outside the principal subspace for the source and target distributions, respectively.
207+
sub_the_same : bool
208+
should the source/target Gaussian HD distributions live in the same principal subspace?
209+
210+
Returns
211+
-------
212+
Xs : ndarray, shape (ns, p)
213+
`ns` observations of size `p` (source)
214+
Xt : ndarray, shape (nt, p)
215+
`nt` observations of size `p` (destination)
216+
pmts : list
217+
a list containing the parameters of the Gaussian HD distributions
218+
219+
.. _references-make_gauss_hd:
220+
References
221+
----------
222+
223+
.. [1] Bouveyron, C. & Corneli, M. ("Scaling Optimal Transport to High-Dimensional Gaussian Distributions")
224+
225+
"""
226+
d = (dim, dim) if isinstance(dim, int) else dim
227+
mu = np.zeros((2, p))
228+
S = []
229+
mu[1, 0] = m_diff
230+
Q = [ortho_group.rvs(p) for _ in range(2)]
231+
232+
if sub_the_same:
233+
Q[1] = Q[0]
234+
235+
S.append(
236+
Q[0]
237+
@ np.diag(np.hstack((np.full(d[0], a[0]), np.full(p - d[0], b[0]))))
238+
@ Q[0].T
239+
)
240+
S.append(
241+
Q[1]
242+
@ np.diag(np.hstack((np.full(d[1], a[1]), np.full(p - d[1], b[1]))))
243+
@ Q[1].T
244+
)
245+
246+
Xs = multivariate_normal.rvs(mean=mu[0], cov=S[0], size=ns)
247+
Xt = multivariate_normal.rvs(mean=mu[1], cov=S[1], size=ns)
248+
249+
ms = mu[0]
250+
mt = mu[1]
251+
ds = d[0]
252+
dt = d[1]
253+
sigma2_s = np.array(b[0])
254+
sigma2_t = np.array(b[1])
255+
ls = np.repeat(a[0], ds) - sigma2_s
256+
lt = np.repeat(a[1], dt) - sigma2_t
257+
Us = Q[0][:, :ds]
258+
Ut = Q[1][:, :dt]
259+
ds = np.array([ds])
260+
dt = np.array([dt])
261+
262+
prmts = {
263+
"ms": ms,
264+
"mt": mt,
265+
"sigma2_s": sigma2_s,
266+
"sigma2_t": sigma2_t,
267+
"ls": ls,
268+
"lt": lt,
269+
"Us": Us,
270+
"Ut": Ut,
271+
"ds": ds,
272+
"dt": dt,
273+
"Cs": S[0],
274+
"Ct": S[1],
275+
}
276+
277+
return Xs, Xt, prmts

0 commit comments

Comments
 (0)