A history of pairwise alignment
My blog: curiouscoding.nl Link to heading

Pairwise alignment:
finding differences between strings
Link to heading
Covid – \(\alpha\), December 2020 Link to heading

Covid – \(\omicron\), December 2021 Link to heading

Pairwise alignment Link to heading
- Find the mutations between two sequences
Dynamic programming Link to heading
Dynamic programming Link to heading
Dynamic programming Link to heading
Dynamic programming Link to heading
Dynamic programming Link to heading
50 000 TB of sequenced DNA → it must be fast Link to heading

Data Center
PhonlamaiPhoto | istockphoto.com

Growth of SRA
Goal:
Fast code
Link to heading
Goal:
High throughput code
Link to heading
Goal:
Optimal throughput code
Link to heading
What is high troughput code? Link to heading
- Complexity
Few operations:
\(\quad O(n^2)\quad\longleftrightarrow\quad O(n)\)
- Efficiency
Fast operations:
memory read, 100 ns \(\quad\longleftrightarrow\quad\) 0.1 ns, addition
- Implementation
Parallel operations:
SIMD, instruction-level parallelism
Lots of work on this problem! Link to heading

Needleman-Wunsch – Quadratic \(O(n^2)\) Link to heading

Can we do better than quadratic? Link to heading
No! (not much anyway) Link to heading
- There is a \(O(n^{2-\varepsilon})\) lower bound assuming SETH.
- One of the best algorithms is four Russians in \(O(n^2 / \lg n)\):
Can we do better than quadratic? – take 2 Link to heading
Yes! BFS / Dijkstra – \(O(ns)\) for distance \(s\) Link to heading
- Visit only states at distance \(\leq s\), within the central \(2s+1\) diagonals.

Diagonal transition – \(O(n + s^2)\) Link to heading
- Greedily extend matches along diagonals → visit \({\leq} s\) states per diagonal

Diagonal transition – \(O(n + s^2)\) Link to heading

A*PA – near-linear, \(3\times\) faster on similar seqs Link to heading

[1] Exact Global Alignment Using A* with Chaining Seed Heuristic and Match Pruning.
RGK and Pesho Ivanov, Bioinformatics 2024.
Worst-case vs avg-case complexity
A*PA heuristics Link to heading

A*PA – not quite linear, and terrible efficiency Link to heading

Intermezzo: array indexing is not \(O(1)\)! Link to heading
Band Doubling – \(O(ns)\) Link to heading
- Compute all states within central \(t\) diagonals for exponentially growing \(t\). Super efficient!

Optimizations Link to heading
Bitpacking (Myers’ 99)
- Computes \(w=64\) states at once by encoding the \(\{-1, 0, +1\}\) differences between adjacent states in a word.
- \(O(ns/w)\)
SIMD: single instruction multiple data, special CPU instructions.
- Operates on e.g. 4 or 8 64-bit words at the same time..
A*PA2 – good efficiency: up to \(19\times\) faster Link to heading
- Band-doubling + bitpacking + SIMD + A*PA

[2] /A*PA2: Up to 19x Faster Exact Global Alignment. WABI 2024.
A*PA: comparison Link to heading

But: Long-read global alignment is just not a problem people have… Link to heading
Alignment modes Link to heading
Semi-global variants Link to heading
… Sassy: 100bp semi-global alignment Link to heading
Approximate String Matching Link to heading
- Find pattern \(P\) in text \(T\).
- \(m := |P|\), \(n := |T|\)
- Allow up to \(k\) unit-cost errors.
- Find all matches.
- IUPAC support: Handle
ACTG,N,YR...
- Not semi-global alignment
- Not \(\Theta(nm/w)\)
- Not new: Lots and LOTS of old literature
ASM in \(O(\lceil n/w\rceil k)\) Link to heading
- Myers’ bitpacking on \(w=64\)-bit blocks.
- “Early break” when all states in block have cost \(>k\), after \(\approx 2k\) rows.
- Horizontal tiling because \(k\ll w\) makes \(O(n \lceil k/w\rceil)\) inefficient.
SIMD: Chunking the text Link to heading
- Split the text in 4 chunks.
- Process 1 chunk per SIMD-lane.
- The blue blocks are all evaluated at the same time!
Sassy 1: search long text at \({>}1\) Gbp/s Link to heading
- Params:
- \(20 \leq |P| \leq 1000\), \(n=10^5\)
- 1 thread, fwd search only
- Results:
- k=3: 1.1 Gbp/s
- k=20: 600 Mbp/s
- 10\(\times\) Edlib, 128\(\times\) parasail
Applications:
- Crispr off-target searching
- Many short patterns, fixed reference → Columba (Renders+ 2025)
- Barcode detection for demultiplexing
- Many short patterns, reads → Batching!
CLI: sassy grep -p <pattern> -k 3 <hg>.fa
Link to heading

Sassy 2: batching \(\gg\) chunking Link to heading
- Text chunking requires
gatheringand transposing - Take pattern suffix of len \(w’\in\{16,32\}\)
- Random DNA has edit distance \(\approx 45\%\).
- \(w’>2k+\varepsilon\) ensures few spurious matches.
- One suffix per SIMD lane.
- Post-process if suffix matches with cost \(\leq k\).
Sassy 2: search at 8 Gbp/s Link to heading
- A: 128 patterns of len 23, 1 thread, \(k\in \{0,3,4\}\). B: \(n=10^5\), \(k=3\).
Sassy 2 Application: Crispr off-target & Barbell Link to heading
- Search a 23bp guide RNA in a human genome with \(k=3\) in 30ms or amortized >100 Gbp/s on 16 threads.
- 3.7\(×\) Sassy1, 35\(×\) Edlib
- Scan Nanopore reads for 96 ONT rapid barcodes with \(k=3\) at 1.2 Gbp/s!
- 4.6\(×\) Sassy1, 45\(×\) Edlib
- Barbell (Beeloo+) is a fast & accurate demultiplexer using Sassy2.
- Poster tonight!
Outlook: Sassy-GPU Link to heading
Extras Link to heading
A*PA: seed heuristic Link to heading

A*PA: gap-chaining seed heuristic Link to heading

A*PA: contours Link to heading

A*PA2: pre-pruning Link to heading
