Skip to content

[ENH] Add Swale (Sequence Weighted Alignment) distance (#425)#3627

Open
CedricConday wants to merge 2 commits into
aeon-toolkit:mainfrom
CedricConday:enh/swale-distance
Open

[ENH] Add Swale (Sequence Weighted Alignment) distance (#425)#3627
CedricConday wants to merge 2 commits into
aeon-toolkit:mainfrom
CedricConday:enh/swale-distance

Conversation

@CedricConday

Copy link
Copy Markdown
Contributor

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 in DISTANCES, 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:

Swale(R,S) = n·g            if m = 0
             m·g            if n = 0
             r  + Swale(Rest(R), Rest(S))                        if |r_1 - s_1| ≤ ε
             max{ g + Swale(Rest(R), S), g + Swale(R, Rest(S)) } otherwise

with match reward r and gap cost g.

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 is 1 - score / (match_reward * min(m, n)) — 0 for identical series, non-negative in general (the score can never exceed that maximum), and requiring match_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), and match_reward=50, gap_penalty=-8 following 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, and pre-commit is clean.

This pull request includes code written with the assistance of AI. The code has not yet been reviewed by a human.

)

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.
@aeon-actions-bot aeon-actions-bot Bot added distances Distances package enhancement New feature, improvement request or other non-bug code enhancement testing Testing related issue or pull request labels Jul 9, 2026
@aeon-actions-bot

Copy link
Copy Markdown
Contributor

Thank you for contributing to aeon

I have added the following labels to this PR based on the title: [ enhancement ].
I have added the following labels to this PR based on the changes made: [ distances, testing ]. Feel free to change these if they do not properly represent the PR.

The Checks tab will show the status of our automated tests. You can click on individual test runs in the tab or "Details" in the panel below to see more information if there is a failure.

If our pre-commit code quality check fails, please run pre-commit locally and push the fixes to your PR branch.

Don't hesitate to ask questions on the aeon Discord channel if you have any.

PR CI actions

These checkboxes will add labels to enable or disable CI functionality for this PR. This may not take effect immediately, and a new commit may be required to run the new configuration.

  • Run pre-commit checks for all files
  • Run mypy typecheck tests
  • Run all pytest tests and configurations
  • Run all notebook example tests
  • Run numba-disabled codecov tests
  • Disable numba cache loading
  • Regenerate expected results for testing
  • Push an empty commit to re-run CI checks

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

distances Distances package enhancement New feature, improvement request or other non-bug code enhancement testing Testing related issue or pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ENH] Implement Sequence Weighted Alignment model (Swale) distance function

1 participant