Foresight.Text.SequenceMatcher (Foresight v0.1.0)

Copy Markdown View Source

Faithful port of Python difflib.SequenceMatcher(None, a, b).ratio() — the Ratcliff-Obershelp similarity Hindsight uses for entity name matching (engine/entity_resolver.py:664).

ratio/2 returns 2.0 * M / T where M is the total number of matched characters across the recursively-discovered longest matching blocks and T = length(a) + length(b). Empty-vs-empty returns 1.0 (difflib's T == 0 special case).

Fidelity scope

CPython's SequenceMatcher has two knobs this port deliberately omits, both provably inert for the entity-name domain it serves:

  • isjunk — Hindsight always passes None, so no element is junk. With no junk, the DP below already yields maximal contiguous runs, and difflib's junk-extension loops never fire. Omitting them is exact, not approximate.
  • autojunk — difflib treats an element as junk when the second sequence has more than 200 items and the element occupies >1% of them. Entity names are far shorter than 200 characters, so autojunk never triggers. This port does not implement it; feeding it a >200-char b with a hot character would diverge from difflib, which is out of scope by construction.

Operates on Unicode code points (String.to_charlist/1), matching Python's per-character iteration over str. Pure and side-effect-free.

Summary

Functions

Ratcliff-Obershelp similarity ratio in [0.0, 1.0], byte-faithful to difflib.SequenceMatcher(None, a, b).ratio() within the fidelity scope above.

Functions

ratio(a, b)

@spec ratio(String.t(), String.t()) :: float()

Ratcliff-Obershelp similarity ratio in [0.0, 1.0], byte-faithful to difflib.SequenceMatcher(None, a, b).ratio() within the fidelity scope above.