Ticket #225: spelling_frequency.diff

File spelling_frequency.diff, 2.6 KB (added by Philip Neustrom, 17 years ago)

An example implementaiton

  • api/omdatabase.cc

    diff -uNrEb xapian-core-1.0.5/api/omdatabase.cc xapian-core-1.0.5-philip/api/omdatabase.cc
    old new  
    4343#include "noreturn.h"
    4444
    4545#include <stdlib.h> // For abs().
     46#include <math.h> // For pow().
    4647
    4748#include <vector>
    4849
     
    384385    string result;
    385386    int edist_best = max_edit_distance;
    386387    Xapian::doccount freq_best = 0;
     388    Xapian::doccount freq_best_edist = 0;
    387389    while (true) {
    388390        TermList *ret = merger->next();
    389391        if (ret) merger = ret;
     
    403405
    404406            // First check the length of the encoded UTF-8 version of term.
    405407            // Each UTF-32 character is 1-4 bytes in UTF-8.
    406             if (abs((long)term.size() - (long)word.size()) > edist_best * 4) {
     408            if (abs((long)term.size() - (long)word.size()) > max_edit_distance* 4) {
    407409                DEBUGLINE(SPELLING, "Lengths much too different");
    408410                continue;
    409411            }
     
    413415            utf32_term.assign(Utf8Iterator(term), Utf8Iterator());
    414416
    415417            if (abs((long)utf32_term.size() - (long)utf32_word.size())
    416                     > edist_best) {
     418                    > max_edit_distance) {
    417419                DEBUGLINE(SPELLING, "Lengths too different");
    418420                continue;
    419421            }
    420422
     423            if ((long)utf32_term.size() <= TRIGRAM_SCORE_THRESHOLD + 1) {
     424                DEBUGLINE(SPELLING, "Term too short");
     425                continue;
     426            }
     427
    421428            int edist = edit_distance_unsigned(&utf32_term[0],
    422429                                               utf32_term.size(),
    423430                                               &utf32_word[0],
    424431                                               utf32_word.size());
    425432            DEBUGLINE(SPELLING, "Edit distance " << edist);
    426             // If we have an exact match, return an empty string since there's
    427             // no correction required.
    428             if (edist == 0) return string();
    429433
    430             if (edist <= edist_best) {
    431434                Xapian::doccount freq = 0;
    432435                for (size_t j = 0; j < internal.size(); ++j)
    433436                    freq += internal[j]->get_spelling_frequency(term);
    434437
    435438                DEBUGLINE(SPELLING, "Freq " << freq << " best " << freq_best);
    436                 if (edist < edist_best || freq > freq_best) {
     439                if (edist <= edist_best && (freq > (max_edit_distance - edist_best)*freq_best_edist)) {
    437440                    DEBUGLINE(SPELLING, "Best so far: \"" << term <<
    438441                                        "\" edist " << edist << " freq " <<
    439442                                        freq);
    440443                    result = term;
    441444                    edist_best = edist;
    442445                    freq_best = freq;
     446                    freq_best_edist = freq;
    443447                }
     448                else if ((freq > pow(freq_best_edist, edist+2)) &&
     449                         ((edist - 2) < edist_best) &&
     450                         (freq > freq_best)) {
     451                    DEBUGLINE(SPELLING, "Best so far: \"" << term <<
     452                                        " freq " <<
     453                                        freq);
     454                    result = term;
     455                    freq_best = freq;
    444456            }
    445457        }
    446458    }