Skip to main content

Lattice Path Edit Distance and romanization-aware string comparison

Project description

mòine

CI PyPI crates.io docs.rs

mòine is a Python and Rust library for romanization-aware string comparison.

It implements Lattice Path Edit Distance (LPED; Kaji, 2023), a distance metric that compares strings through possible reading paths rather than only through visible surface characters.

This is useful when romanized input and written Japanese or Chinese look far apart as strings, but stay close in reading space.

With the package installed and language artifacts downloaded:

>>> import moine

>>> moine.distance("moine", "モイニャ", lang="ja")
2

>>> moine.distance("もいにゃ", "モイニャ", lang="ja")
0

>>> moine.distance("weishiji", "威士忌", lang="zh")
0

>>> moine.distance("布納哈奔", "布納哈本", lang="zh")
0

Name

The project name comes from Moine, a peated malt from Bunnahabhain and one of the developer's favorite Scotch whiskies. In Japanese, the name has several plausible katakana renderings, such as モイニャ, モーイン, and モアンヌ, which makes it a fitting name for a project about readings, spelling variation, and ambiguity in input sequences.

Features

  • Japanese comparison with UniDic-CWJ-derived reading artifacts and separate SudachiDict-derived artifacts.
  • Chinese comparison with CC-CEDICT-derived no-tone pinyin artifacts.
  • Plain string Levenshtein-compatible distance helpers.
  • Lattice-aware Damerau-Levenshtein distance for adjacent transpositions.
  • Combined min(surface Damerau-Levenshtein, LPED) scorer for candidate reranking.
  • Normalized similarity / ratio helpers in 0.0..=1.0.
  • RapidFuzz-inspired APIs such as cdist and partial matching helpers.

Installation

Install the Python package:

pip install moine
uv pip install moine

Install the Rust command-line tool:

cargo install moine

The packages do not bundle dictionary data. Download the language artifacts you need explicitly:

# Default Japanese artifact: UniDic-CWJ
uv run python -m moine download ja

# Explicit Japanese sources
uv run python -m moine download ja-unidic
uv run python -m moine download ja-sudachi

# Chinese artifact: CC-CEDICT
uv run python -m moine download zh

# Same selectors are available from the Rust CLI.
moine download ja
moine download ja-unidic
moine download ja-sudachi
moine download zh

ja is the short default selector for the current Japanese artifact, which is UniDic-CWJ. Use ja-unidic or ja-sudachi when the dictionary source should be explicit.

Quick Start

Use the top-level Python API when you want mòine to load the default dictionary for a language:

import moine

print(moine.distance("もいにゃ", "モイニャ", lang="ja"))  # 0
print(moine.ratio("ピィート", "ピート", lang="ja"))  # 0.7142857142857143
print(moine.partial_ratio("ウイスキー", "ういすきーをのんでいます", lang="ja"))  # 1.0
print(moine.distance("weishiji", "威士忌", lang="zh"))  # 0

Load a dictionary explicitly when you want to control startup cost or artifact location:

import moine

dictionary = moine.load_dict(lang="ja")
moine.set_default_dictionary(dictionary)

print(moine.distance("もいにゃ", "モイニャ", lang="ja"))  # 0

Use cdist for query-by-choice matrices:

import moine

scores = moine.cdist(
    ["もいにゃ", "ぴーと", "ピィート"],
    ["モイニャ", "ピート", "ピーと", "ピィート"],
    lang="ja",
    metric="damerau_distance",
    score_cutoff=1,
)

For search or entity matching, generate candidates with your existing system and use mòine as a reading-aware reranker:

import moine

query = "moine"
candidates = ["モイニャ", "モーイン", "モアンヌ", "ストイーシャ"]

scores = moine.cdist(
    [query],
    candidates,
    lang="ja",
    metric="distance",
)[0]

ranked = sorted(zip(candidates, scores), key=lambda item: item[1])
print(ranked)
# [('モイニャ', 2), ('モーイン', 2), ('モアンヌ', 3), ('ストイーシャ', 7)]

Score interpretation is intentionally simple: distance=0 means the best reading paths are identical, combined_distance is the minimum of surface Damerau-Levenshtein and LPED, distance metrics are smaller-is-better, ratio and normalized_similarity are in 0.0..=1.0 and larger-is-better, and score_cutoff filters in the RapidFuzz style.

Command Line

Most users only need the public runtime commands:

moine download ja
moine download zh
moine list
moine where
moine compare --left "もいにゃ" --right "モイニャ" \
  --artifact-metadata /path/to/moine-unidic-cwj-202512/metadata.yaml
moine chinese-compare --left weishiji --right 威士忌 \
  --artifact-metadata /path/to/moine-cedict-20260520/metadata.yaml

Use moine download ja-unidic for explicit UniDic-CWJ and moine download ja-sudachi for SudachiDict-full.

The artifact bundle, verification, archive, and raw-dictionary inspection commands are maintainer-facing tools for producing and checking release assets. They are documented in docs/development.md and docs/release_process.md.

The public comparison commands can also emit lattice graphs: moine compare --romaji-lattice <PATH> --output-format <dot|svg|png> for Japanese romaji lattices, and moine chinese-compare --pinyin-lattice <PATH> --output-format <dot|svg|png> for Chinese pinyin lattices. Writing SVG or PNG graphs requires the Graphviz dot command to be available in PATH; DOT output does not require that runtime dependency. See CLI usage for rendered examples.

Documentation

Developer and maintainer notes live under docs/, starting with docs/development.md and docs/release_process.md. See CONTRIBUTING.md before opening pull requests.

How It Differs From RapidFuzz

RapidFuzz is the better fit when both inputs should be compared directly as surface strings and you need a broad set of highly optimized fuzzy-matching scorers. mòine focuses on a narrower problem: comparing strings through possible reading paths before edit distance is computed.

Benchmark

Recorded on 2026-06-20. The first table reports scoring time only; dictionary loading is shown separately below.

[!IMPORTANT] RapidFuzz measures surface Levenshtein distance, so it is expected to be much faster. Treat this as a reference for mòine's dictionary-backed reading edit distance, not a same-task speed comparison.

uv run python -m moine download ja
uv run --python python3.14 --with rapidfuzz \
  python scripts/benchmark_distances.py \
  --loops 10000

This is a quick local benchmark command. The release-wheel command used for the recorded table lives in development notes.

Method mean (±std) relative
RapidFuzz Levenshtein 0.15 ± 0.01 us/call 1.00x
mòine ja distance 58.38 ± 109.10 us/call 390x

Fresh dictionary loads from the standard installed artifacts, measured over 100 loads:

Dictionary mean (±std)
UniDic-CWJ 475.23 ms ± 22.41 ms
SudachiDict-full 1959.09 ms ± 43.83 ms
CC-CEDICT 168.82 ms ± 12.47 ms

Limitations

  • mòine does not reproduce the original paper's private search-query-log evaluation.
  • Dictionary-backed comparison requires separately distributed dictionary artifacts.
  • UniDic matching intentionally does not use MeCab/Viterbi costs.
  • Chinese support is Mandarin pinyin only; it does not model Cantonese/Jyutping or non-Mandarin readings.
  • processor, score_hint, NumPy dtype options, and worker parallelism are not part of the current cdist API.

Reference

[!CAUTION] This project is not the official implementation by the paper author.

@inproceedings{kaji-2023-lattice,
    title = "Lattice Path Edit Distance: A {R}omanization-aware Edit Distance for Extracting Misspelling-Correction Pairs from {J}apanese Search Query Logs",
    author = "Kaji, Nobuhiro",
    editor = "Wang, Mingxuan  and
      Zitouni, Imed",
    booktitle = "Proceedings of the 2023 Conference on Empirical Methods in Natural Language Processing: Industry Track",
    month = dec,
    year = "2023",
    address = "Singapore",
    publisher = "Association for Computational Linguistics",
    url = "https://aclanthology.org/2023.emnlp-industry.24/",
    doi = "10.18653/v1/2023.emnlp-industry.24",
    pages = "233--242",
}

License

mòine source code is licensed under either MIT or Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.

Dictionary data is separate. UniDic-derived, SudachiDict-derived, and CC-CEDICT-derived artifacts carry their own license and attribution metadata, and should keep dictionary license information separate from the mòine source-code license. See THIRD_PARTY_NOTICES.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

moine-0.2.1.tar.gz (113.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

moine-0.2.1-cp314-cp314-win_amd64.whl (570.9 kB view details)

Uploaded CPython 3.14Windows x86-64

moine-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl (744.7 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

moine-0.2.1-cp314-cp314-macosx_11_0_arm64.whl (669.9 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

moine-0.2.1-cp313-cp313-win_amd64.whl (570.7 kB view details)

Uploaded CPython 3.13Windows x86-64

moine-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl (744.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

moine-0.2.1-cp313-cp313-macosx_11_0_arm64.whl (669.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

moine-0.2.1-cp312-cp312-win_amd64.whl (571.1 kB view details)

Uploaded CPython 3.12Windows x86-64

moine-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl (745.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

moine-0.2.1-cp312-cp312-macosx_11_0_arm64.whl (670.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

moine-0.2.1-cp311-cp311-win_amd64.whl (576.1 kB view details)

Uploaded CPython 3.11Windows x86-64

moine-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl (749.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

moine-0.2.1-cp311-cp311-macosx_11_0_arm64.whl (672.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file moine-0.2.1.tar.gz.

File metadata

  • Download URL: moine-0.2.1.tar.gz
  • Upload date:
  • Size: 113.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for moine-0.2.1.tar.gz
Algorithm Hash digest
SHA256 9f80266007fc9c08e6022bc946a6bce570f20d2be9f308f26a2aea9d73f232a9
MD5 b5756f2c1611c8a6060aed7cd092fcd8
BLAKE2b-256 42c8c83b879801c21cd3dbb09a71eb83775524083010d7012a5953325fef77de

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1.tar.gz:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: moine-0.2.1-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 570.9 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for moine-0.2.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 4e5c2c977783409a51dfb5ed36a3970b7e35f8627bd89946deb036e85d2f54b2
MD5 494d74ab2ad2049048be6387dca024f7
BLAKE2b-256 b574a75fabbd4a85555ea6040399980c9d6a413af5e8a462ef5c1ef5571d0b30

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp314-cp314-win_amd64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9f63449aacde2af25fa72695978c383674af4088599429e4c4ebfe084bd609f5
MD5 f3676271c1f2aaee0beb3f42f79f2318
BLAKE2b-256 0dfbf0325b980d9ff48b11e57fed9a26ae57a07ed1077984b71c1fd428448a91

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0072a0b77aa5c922d1a1576887f4dbfa3e00d7ddd4d92797ee1e141a4c8b4eeb
MD5 56b4cdbe27dee6ae3663ee119bc9023a
BLAKE2b-256 7021a2d906df5529d765416c602f427a94e37855b6f31efc0ecb8592943e0455

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: moine-0.2.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 570.7 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for moine-0.2.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 065eba618cdb5b8073ab87f3fa001a72a640d9aa7d98b70bcd029cba559c4c73
MD5 44b4e834fc4d5c2978557672a90e97fd
BLAKE2b-256 daa429f062d9ef6fa2b93a4b8702e9223b2800f8219b02f39f5a944b0a5de5ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp313-cp313-win_amd64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5993d7e3cbf6212bde8a9e2980e23f72efdeff8dbda14161ce25e813b7c7947f
MD5 e6dc95a2d120a4b1508a34374418407b
BLAKE2b-256 429802a4786aa100b4f07d44651a5a01d97cadac772cc032e4e3a3014e3b71d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f9dcfc8754d39e7cb9b8c62ca044591bb2492f49b74a9771c236bd1dc72bb0bf
MD5 c0180e7904fbb170a1f3ce9fb0f5e067
BLAKE2b-256 6dadc1ce83ff5f3a464f7f7424baa32b242c8462d73f901b90028d01af1330fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: moine-0.2.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 571.1 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for moine-0.2.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 60362ffbbd92644018d85328f915c17524ec76d4b5c52f661ec982fb2fa5d51c
MD5 d480fac5f03a65642195891e2fee5607
BLAKE2b-256 942afa5365759a288dee23e352dd55d71e6b33bb4bc104aeae78f540705f4b10

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp312-cp312-win_amd64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 033ab36fca52d9db9c02b14cc562b0667d356a0ed66b666420bbe54620426133
MD5 32fa880ba461bb15d031e7c7409cef40
BLAKE2b-256 8e4543bcf82d2cf88a76c9b97053f86b991343ccdcba6ea38f65f15a3e4c3215

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 56a3995b8358b891d56a54a041db9dd71434e080a13b634250b978240450dc84
MD5 ee5de7e0a1a99b29bb3f98fba979a681
BLAKE2b-256 c3cfd001f8f034128f97b52442e509dc5ecc05ffe6a46b042a25c4114a4971b9

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: moine-0.2.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 576.1 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for moine-0.2.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 5a6cbc31ec09bde277e650de66b868c4bd69797c3727a7f2b9d79f88190c5ae8
MD5 1f1831812ba940328a30d6334e450ab5
BLAKE2b-256 2489001b9848d38ea42b2276cb250e327f5cfae454ab728d394d96122f6603ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp311-cp311-win_amd64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 991001da322fc37a313e843f55d23bcf148fe4e1c6393ab8340465fff960d3fb
MD5 d5ce8c3205f8b766caea0096928e7caf
BLAKE2b-256 8b869db2f21893215b7fa8cdc89122d363945c1c04b14cb51ae4fbc1be859528

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moine-0.2.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for moine-0.2.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 00ebf7c750343f55de69202e8910fa7e66c701e6e4dd3138e1c2c03d611115b4
MD5 02eef0a7b6a1963660218d2c3e4b6440
BLAKE2b-256 6392e1ec6940abef8354a688fd2c63c5701d07073c5b2023bd3e1e7ee81ab764

See more details on using hashes here.

Provenance

The following attestation bundles were made for moine-0.2.1-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on tagucci/moine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page