Skip to content

tamil: accusative -னை preserves stem consonant ன் - #279

Open
ithiru wants to merge 1 commit into
snowballstem:mainfrom
ithiru:fix/tamil-accusative-nai
Open

ithiru wants to merge 1 commit into
snowballstem:mainfrom
ithiru:fix/tamil-accusative-nai

Conversation

@ithiru

@ithiru ithiru commented Apr 16, 2026

Copy link
Copy Markdown

Bug

The rule '{nnna}{vs_ai}' (delete) at algorithms/tamil.sbl:279 (inside remove_vetrumai_urupukal — "remove case suffixes") deleted both the consonant (U+0BA9) and the vowel-sign (U+0BC8) when stripping the Tamil accusative case suffix -னை. This left -ன்-ending masculine nouns with a truncated stem that did not match their nominative form, breaking inflection-class collapse across the corpus.

input upstream fixed
கர்ணன் (nom) கர்ணன் கர்ணன்
கர்ணனை (acc) கர்ண கர்ணன்
கர்ணனால் (instr) கர்ணன் கர்ணன்
கர்ணனின் (gen) கர்ணன் கர்ணன்
பீமனை (acc) பீம பீமன்
ஃபவுண்டேஷனை (acc) ஃபவுண்டேஷ ஃபவுண்டேஷன்
ஹோர்மோனை (acc) ஹோர்மோ ஹோர்மோன்

-ர்-ending masculine nouns are not affected: their accusative is -ரை (handled by a different rule that already preserves -ர்). Pronouns shorter than 5 characters (அவன் / அவனை) are not touched because has_min_length requires len > 4.

Fix

Change the rule body from delete to <- '{nnna}{pulli}': instead of deleting the bigram னை, replace it with ன் (consonant + pulli), restoring the canonical nominative form. One-line behavioural change.

Cross-validation against snowball-data

Stemmed the full snowball-data/tamil/voc.txt (443,271 words) with both upstream and patched algorithms. Diff:

  • 2,785 entries change (1.25% of the corpus)
  • 1,283 gain a final ன்/ண் consonant that belongs to the noun stem (-னை directly stripped — the bug). New stems are longer.
  • 1,329 reach a deeper dictionary root because the corrected mid-step now allows downstream rules to fire that previously couldn't (e.g. அதிகாரத்தினை: அதிகாரத்தி -> அதிகாரம், the dictionary form for "authority"). New stems are shorter but more correct.
  • 173 end at the same length but a different consonant.

Manual inspection across each bucket: all changes are corrections, none introduce regressions. The companion data PR (snowball-data#fix/tamil-accusative-nai) regenerates tamil/output.txt so CI passes against this branch.

History

This rule has been unchanged since at least the September 2023 optimization pass. The bug is upstream of all consumers (Python snowballstemmer, the Go blevesearch/snowballstem port, etc.). Tested with snowball master at HEAD before applying the patch.

The rule '{nnna}{vs_ai}' (delete) at line 279 of remove_vetrumai_urupukal
deleted both the consonant ன and the vowel-sign ை when stripping the Tamil
accusative case suffix -னை. This left -ன்-ending masculine nouns with a
truncated stem that did not match their nominative form.

Examples:
  Before                    After
  கர்ணனை -> கர்ண            கர்ணனை -> கர்ணன்
  பீமனை -> பீம              பீமனை -> பீமன்
  ஃபவுண்டேஷனை -> ஃபவுண்டேஷ  ஃபவுண்டேஷனை -> ஃபவுண்டேஷன்
  ஹோர்மோனை -> ஹோர்மோ        ஹோர்மோனை -> ஹோர்மோன்

The fix replaces the deleted bigram with -ன் (consonant + pulli), restoring
the canonical nominative form. Other case suffixes already preserve the stem
consonant, so this brings the accusative in line.

Across the snowball-data tamil voc.txt (443,271 words), this changes the
output for 2,785 words. Manual inspection of the diffs shows all are
either:
- previously truncated -னை forms that now match the nominative (1,283 cases,
  longer stems), or
- chained-suffix words where the corrected mid-step now reaches a deeper
  dictionary root (1,329 cases, shorter stems).

A separate companion PR will update snowball-data/tamil/output.txt.
@ojwb

ojwb commented Apr 16, 2026

Copy link
Copy Markdown
Member

Thanks for raising this.

I ran the change through scripts/stemmer-compare in snowball-data, which shows the effects of a change in terms of how the grouping of words by stem changes - here's the HTML report (the graphs at the bottom show existing on the left, proposed on the right):

compare.html

I can't read Tamil, but tried machine translation which can often give a good enough picture. Unhelpfully Firefox's translation says it supports Tamil in the docs and I can download offline translation data for Tamil, but if I try to translate a page it says translation from Tamil isn't supported. Therefore I've only looked at it with Google's translation, which doesn't seem to translate text in embedded SVG images which is a large part of this particular report.

Based on this, it looks to me like:

  • the 433 merges seem to be overwhelmingly improvements
  • the 120 splits seem to be mostly unhelpful
  • the 2948 words moving between stem groups I can't easily tell (I tried copy and pasting a few words to translate them - e.g. the last group seems an improvement as it splits "hydroscopic" and "hydrophone", and instead groups two words translating to "hydrophone"; it's too laborious to translate enough samples like this to really get an accurate picture though)

From what I can see, I wonder if there's an additional change which would help this one - either a condition on when we do this, or (I suspect more likely) adjusting another rule to avoid many of the splits (and probably to avoid unhelpful moves between groups). Can you have a look through the attached compare.html and see what you think?

@ojwb

ojwb commented Apr 17, 2026

Copy link
Copy Markdown
Member

Related to evaluating this, the current word list we have for tamil seems too large. Looking at the history, the original word list was 433,918 words extracted from tamil wordnet. It seems this was just all of the words, so will include a lot of very obscure and rare words and forms of words, whereas we really want a representative sample of words that the stemmer will actually encounter in practice.

For licensing reasons, instead of the wordnet list we extracted a list from a 2018 dump of Tamil wikipedia - I wrote in snowballstem/snowball-data#1 :

So I've added a Tamil wordlist extracted from a Tamil Wikipedia dump, along with the simple script used to generate it (which essentially just collates matches for the regexp \b[\x{b80}-\x{bff}]+\b and then outputs any which occur 3 or more times). This contains 443271 unique words.

I didn't record why I chose a threshold of >= 3 occurrences, but I strongly suspect I was just trying to match the same approximate number of entries (since 443271 is close to 433918).

However the original 433918 likely includes obscure words and rare forms of words which didn't appear 3 times in wikipedia, so selecting a similar number of words from wikipedia based on frequency probably included a significant proportion of typos and other junk non-words. We've extracted wordlists for some other languages from wikipedia dumps, and experience from that suggests to me that a threshold of 3 won't work well - it's much lower than we've typically used: it looks like the lowest threshold otherwise was 7 for Indonesian (which had a relatively low number of pages on wikipedia), but otherwise it's at least 10.

Aside from Arabic (where the current wordlist was created mechanically by applying grammar rules to root words which produced an overly complete list which we really need to replace), the current Tamil vocabulary is ~2.4 times larger than the next largest and more than 8 times larger than the average.

Perhaps we should sort out a smaller, cleaner wordlist first as junk in the current one may be obscuring the results. I fetched the latest Tamil wikipedia dump and it's grown significantly since 2018, which should mean we can now get a better list of words of a given size. I'll try processing it further.

ithiru added a commit to ithiru/snowball that referenced this pull request Apr 17, 2026
Previously, remove_pronoun_prefixes unconditionally stripped any initial
அ-/இ-/உ- + consonant + pulli cluster, treating it as a demonstrative-
pronoun contraction. In modern Tamil corpora, the க் and ங் variants of
that cluster (அக்-, அங்-, இக்-, இங்-, உக்-, உங்-) almost always mark the
first syllable of Sanskrit-origin proper nouns and loanwords, not
pronominal contractions. The rule therefore damaged names like
அக்னி (Agni), அக்ரூரன் (Akrura), அங்கதன் (Angada), அங்கதேசம் (Anga
country), அக்ஷன் (Aksha), and compound forms like அக்னிஹோத்ரம்,
அக்னிபாசம், அக்னிவர்ணன், reducing them to suffixes of their own
canonicals (னி, ரூரன், கதன், கதேசம், ...).

Evidence: an over-stemming audit across a 27,015-entity literary corpus
(venmurasu.in, 27 books) found 269 distinct entity names whose current
Snowball stem is a proper suffix of the canonical form because of this
rule. The overwhelming majority of the dropped prefixes are of the form
அக்- / அங்-; other consonants in the among list seed many fewer false
positives.

Fix:

1) Drop {ka} and {nga} from the remove_pronoun_prefixes among. The
   remaining eight consonants ({ca}, {tha}, {va}, {na}, {pa}, {ma},
   {ya}, {nya}) continue to strip where they historically did.

2) Guard both remove_question_prefixes and remove_pronoun_prefixes
   with a minimum-length check ($(len >= 7)) so the three-character
   prefix is only stripped when at least four characters remain.
   Without this, short forms like அக்கம் over-strip to கம் and lose
   identity.

Related: snowballstem#279 (Tamil -னை accusative fix).

Companion PR on snowballstem/snowball-data regenerates
tamil/output.txt and adds explicit test vectors for the six
previously-missing audit hot spots (அக்ரூரன், அக்ஷன், அக்னிஹோத்ரம்,
அக்னிபாசம், அக்னிவர்ணன், அக்னிதத்தன்). அக்னி, அங்கதன், and
அங்கதேசம் were already present in the vocabulary and now stem to
themselves.

Signed-off-by: Thiru <techy@thiru.in>
@ojwb

ojwb commented May 25, 2026

Copy link
Copy Markdown
Member

@ithiru Ping - I wonder if you missed my comments and questions above as it's been over a month without a response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants