UNPKG

@a-s8h/liblevenshtein

Version:

Various utilities regarding Levenshtein transducers.

142 lines (120 loc) 4.67 kB
// Generated by CoffeeScript 1.7.1 /** * The algorithm for imitating Levenshtein automata was taken from the * following journal article: * * @ARTICLE{Schulz02faststring, * author = {Klaus Schulz and Stoyan Mihov}, * title = {Fast String Correction with Levenshtein-Automata}, * journal = {INTERNATIONAL JOURNAL OF DOCUMENT ANALYSIS AND RECOGNITION}, * year = {2002}, * volume = {5}, * pages = {67--85} * } * * As well, this Master Thesis helped me understand its concepts: * * www.fmi.uni-sofia.bg/fmi/logic/theses/mitankin-en.pdf * * The supervisor of the student who submitted the thesis was one of the * authors of the journal article, above. * * The algorithm for constructing a DAWG (Direct Acyclic Word Graph) from the * input dictionary of words (DAWGs are otherwise known as an MA-FSA, or * Minimal Acyclic Finite-State Automata), was taken and modified from the * following blog from Steve Hanov: * * http://stevehanov.ca/blog/index.php?id=115 * * The algorithm therein was taken from the following paper: * * @MISC{Daciuk00incrementalconstruction, * author = {Jan Daciuk and Bruce W. Watson and Richard E. Watson and Stoyan Mihov}, * title = {Incremental Construction of Minimal Acyclic Finite-State Automata}, * year = {2000} * } */ (function() { var Transducer, global, __hasProp = {}.hasOwnProperty; Transducer = (function() { Transducer.prototype['minimum_distance'] = function(state, w) { throw new Error('minimum_distance not specified on construction'); }; Transducer.prototype['build_matches'] = function() { throw new Error('build_matches not specified on construction'); }; Transducer.prototype['initial_state'] = function() { throw new Error('initial_state not specified on construction'); }; Transducer.prototype['root'] = function() { throw new Error('root not specified on construction'); }; Transducer.prototype['edges'] = function(q_D) { throw new Error('edges not specified on construction'); }; Transducer.prototype['is_final'] = function(q_D) { throw new Error('is_final not specified on construction'); }; Transducer.prototype['transform'] = function(matches) { throw new Error('transform not specified on construction'); }; Transducer.prototype['transition_for_state'] = function(n) { throw new Error('transition_for_state not specified on construction'); }; Transducer.prototype['characteristic_vector'] = function(x, term, k, i) { throw new Error('characteristic_vector not specified on construction'); }; Transducer.prototype['push'] = function(matches, candidate) { throw new Error('push not specified on construction'); }; Transducer.prototype['default_edit_distance'] = function() { throw new Error('default_edit_distance not specified on construction'); }; function Transducer(attributes) { var attribute; for (attribute in attributes) { if (!__hasProp.call(attributes, attribute)) continue; this[attribute] = attributes[attribute]; } } Transducer.prototype['transduce'] = function(term, n) { var M, V, a, b, distance, i, k, matches, next_M, next_V, next_q_D, q_D, stack, transition, vector, w, x, _ref, _ref1; if (typeof n !== 'number') { n = this['default_edit_distance'](); } w = term.length; transition = this['transition_for_state'](n); matches = this['build_matches'](); stack = [['', this['root'](), this['initial_state']()]]; while (stack.length > 0) { _ref = stack['pop'](), V = _ref[0], q_D = _ref[1], M = _ref[2]; i = M[0][0]; a = 2 * n + 1; b = w - i; k = a < b ? a : b; _ref1 = this['edges'](q_D); for (x in _ref1) { next_q_D = _ref1[x]; vector = this['characteristic_vector'](x, term, k, i); next_M = transition(M, vector); if (next_M) { next_V = V + x; stack.push([next_V, next_q_D, next_M]); if (this['is_final'](next_q_D)) { distance = this['minimum_distance'](next_M, w); if (distance <= n) { this['push'](matches, [next_V, distance]); } } } } } return this['transform'](matches); }; return Transducer; })(); global = typeof exports === 'object' ? exports : typeof window === 'object' ? window : this; global['levenshtein'] || (global['levenshtein'] = {}); global['levenshtein']['Transducer'] = Transducer; }).call(this);