Add `soft_barycenter_average` (in `_ba_soft.py`): a gradient-based barycentre
that minimises a soft elastic objective with `scipy.optimize.minimize`
(L-BFGS-B) using the private soft-DTW / soft-MSM gradients. Wired into
`elastic_barycenter_average` as `method="soft"` and into the averaging callable
registry, exported alongside `VALID_SOFT_BA_METHODS`.
Clean separation (no soft distances in discrete BA): soft distances are only
averaged via `method="soft"`. `soft_dtw` is removed from
`VALID_BA_DISTANCE_METHODS` and from `_get_alignment_path`, and early validation
rejects `method="soft"` with a hard distance and discrete methods with a soft
distance. The discrete-BA test list drops `soft_dtw` and the temporary
`test_kasba` skip is reverted.
Fixes over the prototype:
- `return_distances_to_center` now recomputes distances at the optimised
barycentre instead of returning the initial values.
- Multivariate soft-MSM averaging accumulates the gradient per channel
(independent), matching the soft-MSM distance; the prototype assigned a 1D
gradient into a 2D slot and never worked for soft-MSM.
- Threading uses `numba_thread_handler`; docstring covers both soft distances.
- `_ba_setup` gains `compute_previous_cost` so the soft path skips the upfront
pairwise-cost computation.
Tests parametrise over soft-DTW and soft-MSM, and validate the soft-DTW
barycentre against tslearn's `softdtw_barycenter`.
Reference Issues/PRs
Third of the soft-distance stack. Stacked on #3508 (soft-MSM distance), which is stacked on #3483. Please review/merge those first; this branch targets #3508 and the diff shrinks as they merge.
What does this implement/fix?
Adds gradient-based soft barycentre averaging.
soft_barycenter_average(new_ba_soft.py) minimises a differentiable soft elastic objective withscipy.optimize.minimize(L-BFGS-B), using the private soft-DTW / soft-MSM gradients from the earlier PRs. It is wired intoelastic_barycenter_averageasmethod="soft", added to the averaging callable registry, and exported alongsideVALID_SOFT_BA_METHODS.Clean separation — soft distances only via
method="soft". Soft distances are not used by the discrete BA methods (a soft distance has an alignment distribution, not a single hard path, so DBA-style discrete realignment is ill-defined and was a no-op).soft_dtwis removed fromVALID_BA_DISTANCE_METHODSand from_get_alignment_path; early validation rejectsmethod="soft"with a hard distance and the discrete methods with a soft distance. The discrete-BA test list dropssoft_dtwand the temporarytest_kasbaskip added in #3483 is reverted.Fixes over the prototype:
return_distances_to_centernow recomputes the distances at the optimised barycentre instead of returning the initial (inf) values from setup.numba_thread_handler(the prototype imported a module that does not exist onmain); the docstring covers both soft distances._ba_setupgains acompute_previous_costflag so the soft path skips the upfront pairwise-cost computation.Does your contribution introduce a new dependency?
No. (
tslearn, already optional, is used only as a guarded test oracle.)Test plan
test_soft_ba.pyparametrised over soft-DTW and soft-MSM: shape/finiteness (uni + multivariate),return_cost/return_distances_to_center, weights change the result, single-series passthrough, themethod="soft"validation matrix, and dispatch-equals-direct.softdtw_barycenter(guarded withimportorskip).aeon/clustering/averagingsuite +test_k_means(402 passed) with the discrete-BA changes, and the soft BA tests. Pre-commit passes.