[ENH] Add Swale (Sequence Weighted Alignment) distance (#425)#3627
[ENH] Add Swale (Sequence Weighted Alignment) distance (#425)#3627CedricConday wants to merge 2 commits into
Conversation
) Direct numba implementation of the Swale distance (Morse & Patel, SIGMOD 2007), an epsilon-threshold elastic measure that combines a match reward with a gap penalty. Follows the existing elastic-distance pattern (distance, cost matrix, pairwise, alignment path). The reward-based similarity score is converted to a distance the same way as LCSS, 1 - score / (match_reward * min(m, n)), giving a non-negative distance that is 0 for identical series.
Thank you for contributing to
|
Swale is an LCSS-family similarity measure: its cost matrix is the padded (m+1, n+1) DP table and its distance is the normalised score 1 - score / (match_reward * min(m, n)). The shared distance tests were treating it as a plain (m, n) / bottom-right-cell distance, so test_cost_matrix and the sklearn-compatibility knn tests failed across the whole matrix. - test_cost_matrix: assert the (m+1, n+1) shape and the match-reward-weighted distance derivation for swale, mirroring the existing lcss handling. - test_sklearn_compatibility: skip swale alongside lcss/edr (issue aeon-toolkit#882), since these similarity-derived measures tie-break differently between aeon and sklearn knn.
4f771f5 to
d67b034
Compare
Fixes #425.
Adds the Swale (Sequence Weighted ALignmEnt) distance from Morse & Patel, "An efficient and accurate method for evaluating time series similarity" (SIGMOD 2007), as a numba elastic distance modelled on the existing ones (
_lcss.py,_erp.py). It provides the full API —swale_distance,swale_cost_matrix,swale_pairwise_distance,swale_alignment_path— and is registered inDISTANCES, so it is covered by the parametrised distance tests.Swale is an ε-threshold measure like LCSS and EDR, but it scores both a reward for matches and a penalty for gaps, using the recurrence from Definition 5.1 of the paper:
with match reward
rand gap costg.Similarity → distance (the main thing to review). The raw recurrence is a similarity (higher = more similar), which does not fit the distances framework (non-negativity, self-distance 0). I convert it the same way LCSS does: the maximum attainable score is
match_reward * min(m, n), so the distance is1 - score / (match_reward * min(m, n))— 0 for identical series, non-negative in general (the score can never exceed that maximum), and requiringmatch_reward > 0. Happy to change the convention if you'd prefer a different normalisation, or to expose the raw similarity instead.Defaults.
epsilon=1.0(as LCSS), andmatch_reward=50,gap_penalty=-8following the reward/penalty ratio the paper trains on its ASL data — also a reasonable thing to reconsider.Correctness. I validated the DP against an independent naive recursive implementation of Definition 5.1: exact match (0 error) across 300 random unequal-length cases. The committed expected values were then generated from that verified implementation. The full
aeon/distances/tests/suite passes (513 passed), including the non-negativity, symmetry, unequal-length and single-point checks, andpre-commitis clean.This pull request includes code written with the assistance of AI. The code has not yet been reviewed by a human.