Ticket #225: spelling_frequency_updated.patch

File spelling_frequency_updated.patch, 2.6 KB (added by Olly Betts, 14 years ago)

Patch updated for trunk

  • api/omdatabase.cc

     
    4343#include "ortermlist.h"
    4444#include "noreturn.h"
    4545
     46#include <cmath> // For pow().
    4647#include <cstdlib> // For abs().
    4748
    4849#include <cstring>
     
    574575    string result;
    575576    int edist_best = max_edit_distance;
    576577    Xapian::doccount freq_best = 0;
     578    Xapian::doccount freq_best_edist = 0;
    577579    while (true) {
    578580        TermList *ret = merger->next();
    579581        if (ret) merger.reset(ret);
     
    593595
    594596            // First check the length of the encoded UTF-8 version of term.
    595597            // Each UTF-32 character is 1-4 bytes in UTF-8.
    596             if (abs(long(term.size()) - long(word.size())) > edist_best * 4) {
     598            if (abs(long(term.size()) - long(word.size())) > max_edit_distance * 4) {
    597599                LOGLINE(SPELLING, "Lengths much too different");
    598600                continue;
    599601            }
     
    603605            utf32_term.assign(Utf8Iterator(term), Utf8Iterator());
    604606
    605607            if (abs(long(utf32_term.size()) - long(utf32_word.size()))
    606                     > edist_best) {
     608                    > max_edit_distance) {
    607609                LOGLINE(SPELLING, "Lengths too different");
    608610                continue;
    609611            }
     
    613615                continue;
    614616            }
    615617
     618            if ((long)utf32_term.size() <= TRIGRAM_SCORE_THRESHOLD + 1) {
     619                LOGLINE(SPELLING, "Term too short");
     620                continue;
     621            }
     622
    616623            int edist = edit_distance_unsigned(&utf32_term[0],
    617624                                               int(utf32_term.size()),
    618625                                               &utf32_word[0],
    619626                                               int(utf32_word.size()),
    620627                                               edist_best);
    621628            LOGLINE(SPELLING, "Edit distance " << edist);
    622             // If we have an exact match, return an empty string since there's
    623             // no correction required.
    624             if (edist == 0) RETURN(string());
    625629
    626             if (edist <= edist_best) {
     630            {
    627631                Xapian::doccount freq = 0;
    628632                for (size_t j = 0; j < internal.size(); ++j)
    629633                    freq += internal[j]->get_spelling_frequency(term);
    630634
    631635                LOGLINE(SPELLING, "Freq " << freq << " best " << freq_best);
    632                 if (edist < edist_best || freq > freq_best) {
     636                if (edist <= edist_best && (freq > (max_edit_distance - edist_best)*freq_best_edist)) {
    633637                    LOGLINE(SPELLING, "Best so far: \"" << term <<
    634638                                      "\" edist " << edist << " freq " << freq);
    635639                    result = term;
    636640                    edist_best = edist;
    637641                    freq_best = freq;
     642                    freq_best_edist = freq;
     643                }
     644                else if ((freq > pow(freq_best_edist, edist+2)) &&
     645                         ((edist - 2) < edist_best) &&
     646                         (freq > freq_best)) {
     647                    LOGLINE(SPELLING, "Best so far: \"" << term <<
     648                                        " freq " <<
     649                                        freq);
     650                    result = term;
     651                    freq_best = freq;
    638652                }
    639653            }
    640654        }