signature:
def stem ( self , word , max_word_length = 20 , max_acro_length = 8 , return_rule_no = False , var = 'standard' , ) :
    """Return UEA - Lite stem .
 Parameters
 word : str
 The word to stem
 max _ word _ length : int
 The maximum word length allowed
 max _ acro _ length : int
 The maximum acronym length allowed
 return _ rule _ no : bool
 If True , returns the stem along with rule number
 var : str
 Variant rules to use :
 - ` ` Adams ` ` to use Jason Adams ' rules
 - ` ` Perl ` ` to use the original Perl rules
 Returns
 str or ( str , int )
 Word stem
 Examples
 > > > uealite ( ' readings ' )
 ' read '
 > > > uealite ( ' insulted ' )
 ' insult '
 > > > uealite ( ' cussed ' )
 ' cuss '
 > > > uealite ( ' fancies ' )
 ' fancy '
 > > > uealite ( ' eroded ' )
 ' erode '"""

implementation:
def _stem_with_duplicate_character_check ( word , del_len ) :
    if word [ - 1 ] == 's' :
        del_len += 1
    stemmed_word = word [ : - del_len ]
    if re_match ( r'.*(\w)\1$' , stemmed_word ) :
        stemmed_word = stemmed_word [ : - 1 ]
    return stemmed_word
def _stem ( word ) :
    stemmed_word = word
    rule_no = 0
    if not word :
        return word , 0
    if word in self . _problem_words or ( word == 'menses' and var == 'Adams' ) :
        return word , 90
    if max_word_length and len ( word ) > max_word_length :
        return word , 95
    if "'" in word :
        if word [ - 2 : ] in { "'s" , "'S" } :
            stemmed_word = word [ : - 2 ]
        if word [ - 1 : ] == "'" :
            stemmed_word = word [ : - 1 ]
        stemmed_word = stemmed_word . replace ( "n't" , 'not' )
        stemmed_word = stemmed_word . replace ( "'ve" , 'have' )
        stemmed_word = stemmed_word . replace ( "'re" , 'are' )
        stemmed_word = stemmed_word . replace ( "'m" , 'am' )
        return stemmed_word , 94
    if word . isdigit ( ) :
        return word , 90.3
    else :
        hyphen = word . find ( '-' )
        if len ( word ) > hyphen > 0 :
            if ( word [ : hyphen ] . isalpha ( ) and word [ hyphen + 1 : ] . isalpha ( ) ) :
                return word , 90.2
            else :
                return word , 90.1
        elif '_' in word :
            return word , 90
        elif word [ - 1 ] == 's' and word [ : - 1 ] . isupper ( ) :
            if var == 'Adams' and len ( word ) - 1 > max_acro_length :
                return word , 96
            return word [ : - 1 ] , 91.1
        elif word . isupper ( ) :
            if var == 'Adams' and len ( word ) > max_acro_length :
                return word , 96
            return word , 91
        elif re_match ( r'^.*[A-Z].*[A-Z].*$' , word ) :
            return word , 92
        elif word [ 0 ] . isupper ( ) :
            return word , 93
        elif var == 'Adams' and re_match ( r'^[a-z](|[rl])(ing|ed)$' , word ) :
            return word , 97
    for n in range ( 7 , 1 , - 1 ) :
        if word [ - n : ] in self . _rules [ var ] [ n ] :
            rule_no , del_len , add_str = self . _rules [ var ] [ n ] [ word [ - n : ] ]
            if del_len :
                stemmed_word = word [ : - del_len ]
            else :
                stemmed_word = word
            if add_str :
                stemmed_word += add_str
            break
    if not rule_no :
        if re_match ( r'.*\w\wings?$' , word ) : # rule 58
            stemmed_word = _stem_with_duplicate_character_check ( word , 3 )
            rule_no = 58
        elif re_match ( r'.*\w\weds?$' , word ) : # rule 62
            stemmed_word = _stem_with_duplicate_character_check ( word , 2 )
            rule_no = 62
        elif word [ - 1 ] == 's' : # rule 68
            stemmed_word = word [ : - 1 ]
            rule_no = 68
    return stemmed_word , rule_no
stem , rule_no = _stem ( word )
if return_rule_no :
    return stem , rule_no
return stem


signature:
def _sb_r1 ( self , term , r1_prefixes = None ) :
    """Return the R1 region , as defined in the Porter2 specification .
 Parameters
 term : str
 The term to examine
 r1 _ prefixes : set
 Prefixes to consider
 Returns
 int
 Length of the R1 region"""

implementation:
vowel_found = False
if hasattr ( r1_prefixes , '__iter__' ) :
    for prefix in r1_prefixes :
        if term [ : len ( prefix ) ] == prefix :
            return len ( prefix )
for i in range ( len ( term ) ) :
    if not vowel_found and term [ i ] in self . _vowels :
        vowel_found = True
    elif vowel_found and term [ i ] not in self . _vowels :
        return i + 1
return len ( term )


signature:
def _sb_r2 ( self , term , r1_prefixes = None ) :
    """Return the R2 region , as defined in the Porter2 specification .
 Parameters
 term : str
 The term to examine
 r1 _ prefixes : set
 Prefixes to consider
 Returns
 int
 Length of the R1 region"""

implementation:
r1_start = self . _sb_r1 ( term , r1_prefixes )
return r1_start + self . _sb_r1 ( term [ r1_start : ] )


signature:
def _sb_ends_in_short_syllable ( self , term ) :
    """Return True iff term ends in a short syllable .
 ( . . . according to the Porter2 specification . )
 NB : This is akin to the CVC test from the Porter stemmer . The
 description is unfortunately poor / ambiguous .
 Parameters
 term : str
 The term to examine
 Returns
 bool
 True iff term ends in a short syllable"""

implementation:
if not term :
    return False
if len ( term ) == 2 :
    if term [ - 2 ] in self . _vowels and term [ - 1 ] not in self . _vowels :
        return True
elif len ( term ) >= 3 :
    if ( term [ - 3 ] not in self . _vowels and term [ - 2 ] in self . _vowels and term [ - 1 ] in self . _codanonvowels ) :
        return True
return False


signature:
def _sb_short_word ( self , term , r1_prefixes = None ) :
    """Return True iff term is a short word .
 ( . . . according to the Porter2 specification . )
 Parameters
 term : str
 The term to examine
 r1 _ prefixes : set
 Prefixes to consider
 Returns
 bool
 True iff term is a short word"""

implementation:
if self . _sb_r1 ( term , r1_prefixes ) == len ( term ) and self . _sb_ends_in_short_syllable ( term ) :
    return True
return False


signature:
def _sb_has_vowel ( self , term ) :
    """Return Porter helper function _ sb _ has _ vowel value .
 Parameters
 term : str
 The term to examine
 Returns
 bool
 True iff a vowel exists in the term ( as defined in the Porter
 stemmer definition )"""

implementation:
for letter in term :
    if letter in self . _vowels :
        return True
return False


signature:
def encode ( self , word , max_length = 8 ) :
    """Return the eudex phonetic hash of a word .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length in bits of the code returned ( default 8)
 Returns
 int
 The eudex hash
 Examples
 > > > pe = Eudex ( )
 > > > pe . encode ( ' Colin ' )
 432345564238053650
 > > > pe . encode ( ' Christopher ' )
 433648490138894409
 > > > pe . encode ( ' Niall ' )
 648518346341351840
 > > > pe . encode ( ' Smith ' )
 720575940412906756
 > > > pe . encode ( ' Schmidt ' )
 720589151732307997"""

implementation:
# Lowercase input & filter unknown characters
word = '' . join ( char for char in word . lower ( ) if char in self . _initial_phones )
if not word :
    word = '÷'
# Perform initial eudex coding of each character
values = [ self . _initial_phones [ word [ 0 ] ] ]
values += [ self . _trailing_phones [ char ] for char in word [ 1 : ] ]
# Right - shift by one to determine if second instance should be skipped
shifted_values = [ _ >> 1 for _ in values ]
condensed_values = [ values [ 0 ] ]
for n in range ( 1 , len ( shifted_values ) ) :
    if shifted_values [ n ] != shifted_values [ n - 1 ] :
        condensed_values . append ( values [ n ] )
# Add padding after first character & trim beyond max _ length
values = ( [ condensed_values [ 0 ] ] + [ 0 ] * max ( 0 , max_length - len ( condensed_values ) ) + condensed_values [ 1 : max_length ] )
# Combine individual character values into eudex hash
hash_value = 0
for val in values :
    hash_value = ( hash_value << 8 ) | val
return hash_value


signature:
def roger_root ( word , max_length = 5 , zero_pad = True ) :
    """Return the Roger Root code for a word .
 This is a wrapper for : py : meth : ` RogerRoot . encode ` .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The maximum length ( default 5 ) of the code to return
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length string
 Returns
 str
 The Roger Root code
 Examples
 > > > roger _ root ( ' Christopher ' )
 '06401'
 > > > roger _ root ( ' Niall ' )
 '02500'
 > > > roger _ root ( ' Smith ' )
 '00310'
 > > > roger _ root ( ' Schmidt ' )
 '06310'"""

implementation: return RogerRoot ( ) . encode ( word , max_length , zero_pad )


signature:
def encode ( self , word , max_length = 5 , zero_pad = True ) :
    """Return the Roger Root code for a word .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The maximum length ( default 5 ) of the code to return
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length
 string
 Returns
 str
 The Roger Root code
 Examples
 > > > roger _ root ( ' Christopher ' )
 '06401'
 > > > roger _ root ( ' Niall ' )
 '02500'
 > > > roger _ root ( ' Smith ' )
 '00310'
 > > > roger _ root ( ' Schmidt ' )
 '06310'"""

implementation:
# uppercase , normalize , decompose , and filter non - A - Z out
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = word . replace ( 'ß' , 'SS' )
word = '' . join ( c for c in word if c in self . _uc_set )
code = ''
pos = 0
# Do first digit ( s ) first
for num in range ( 4 , 0 , - 1 ) :
    if word [ : num ] in self . _init_patterns [ num ] :
        code = self . _init_patterns [ num ] [ word [ : num ] ]
        pos += num
        break
# Then code subsequent digits
while pos < len ( word ) :
    for num in range ( 4 , 0 , - 1 ) : # pragma : no branch
        if word [ pos : pos + num ] in self . _med_patterns [ num ] :
            code += self . _med_patterns [ num ] [ word [ pos : pos + num ] ]
            pos += num
            break
code = self . _delete_consecutive_repeats ( code )
code = code . replace ( '*' , '' )
if zero_pad :
    code += '0' * max_length
return code [ : max_length ]


signature:
def _to_alpha ( self , num ) :
    """Convert a Kölner Phonetik code from numeric to alphabetic .
 Parameters
 num : str or int
 A numeric Kölner Phonetik representation
 Returns
 str
 An alphabetic representation of the same word
 Examples
 > > > pe = Koelner ( )
 > > > pe . _ to _ alpha ( ' 862 ' )
 ' SNT '
 > > > pe . _ to _ alpha ( ' 657 ' )
 ' NLR '
 > > > pe . _ to _ alpha ( ' 86766 ' )
 ' SNRNN '"""

implementation:
num = '' . join ( c for c in text_type ( num ) if c in self . _num_set )
return num . translate ( self . _num_trans )


signature:
def lein ( word , max_length = 4 , zero_pad = True ) :
    """Return the Lein code for a word .
 This is a wrapper for : py : meth : ` Lein . encode ` .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 4)
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length string
 Returns
 str
 The Lein code
 Examples
 > > > lein ( ' Christopher ' )
 ' C351'
 > > > lein ( ' Niall ' )
 ' N300'
 > > > lein ( ' Smith ' )
 ' S210'
 > > > lein ( ' Schmidt ' )
 ' S521'"""

implementation: return Lein ( ) . encode ( word , max_length , zero_pad )


signature:
def encode ( self , word , max_length = 4 , zero_pad = True ) :
    """Return the Lein code for a word .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 4)
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length
 string
 Returns
 str
 The Lein code
 Examples
 > > > pe = Lein ( )
 > > > pe . encode ( ' Christopher ' )
 ' C351'
 > > > pe . encode ( ' Niall ' )
 ' N300'
 > > > pe . encode ( ' Smith ' )
 ' S210'
 > > > pe . encode ( ' Schmidt ' )
 ' S521'"""

implementation:
# uppercase , normalize , decompose , and filter non - A - Z out
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = word . replace ( 'ß' , 'SS' )
word = '' . join ( c for c in word if c in self . _uc_set )
code = word [ : 1 ]
# Rule 1
word = word [ 1 : ] . translate ( self . _del_trans )
# Rule 2
word = self . _delete_consecutive_repeats ( word )
# Rule 3
code += word . translate ( self . _trans )
# Rule 4
if zero_pad :
    code += '0' * max_length
# Rule 4
return code [ : max_length ]


signature:
def _get_qgrams ( self , src , tar , qval = 0 , skip = 0 ) :
    """Return the Q - Grams in src & tar .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 skip : int
 The number of characters to skip ( only works when src and tar are
 strings )
 Returns
 tuple of Counters
 Q - Grams
 Examples
 > > > pe = _ TokenDistance ( )
 > > > pe . _ get _ qgrams ( ' AT ' , ' TT ' , qval = 2)
 ( QGrams ( { ' $ A ' : 1 , ' AT ' : 1 , ' T # ' : 1 } ) ,
 QGrams ( { ' $ T ' : 1 , ' TT ' : 1 , ' T # ' : 1 } ) )"""

implementation:
if isinstance ( src , Counter ) and isinstance ( tar , Counter ) :
    return src , tar
if qval > 0 :
    return QGrams ( src , qval , '$#' , skip ) , QGrams ( tar , qval , '$#' , skip )
return Counter ( src . strip ( ) . split ( ) ) , Counter ( tar . strip ( ) . split ( ) )


signature:
def rle_encode ( text , use_bwt = True ) :
    r"""Perform encoding of run - length - encoding ( RLE ) .
 This is a wrapper for : py : meth : ` RLE . encode ` .
 Parameters
 text : str
 A text string to encode
 use _ bwt : bool
 Indicates whether to perform BWT encoding before RLE encoding
 Returns
 str
 Word decoded by RLE
 Examples
 > > > rle _ encode ( ' align ' )
 ' n \ x00ilag '
 > > > rle _ encode ( ' align ' , use _ bwt = False )
 ' align '
 > > > rle _ encode ( ' banana ' )
 ' annb \ x00aa '
 > > > rle _ encode ( ' banana ' , use _ bwt = False )
 ' banana '
 > > > rle _ encode ( ' aaabaabababa ' )
 ' ab \ x00abbab5a '
 > > > rle _ encode ( ' aaabaabababa ' , False )
 '3abaabababa '"""

implementation:
if use_bwt :
    text = BWT ( ) . encode ( text )
return RLE ( ) . encode ( text )


signature:
def rle_decode ( text , use_bwt = True ) :
    r"""Perform decoding of run - length - encoding ( RLE ) .
 This is a wrapper for : py : meth : ` RLE . decode ` .
 Parameters
 text : str
 A text string to decode
 use _ bwt : bool
 Indicates whether to perform BWT decoding after RLE decoding
 Returns
 str
 Word decoded by RLE
 Examples
 > > > rle _ decode ( ' n \ x00ilag ' )
 ' align '
 > > > rle _ decode ( ' align ' , use _ bwt = False )
 ' align '
 > > > rle _ decode ( ' annb \ x00aa ' )
 ' banana '
 > > > rle _ decode ( ' banana ' , use _ bwt = False )
 ' banana '
 > > > rle _ decode ( ' ab \ x00abbab5a ' )
 ' aaabaabababa '
 > > > rle _ decode ( ' 3abaabababa ' , False )
 ' aaabaabababa '"""

implementation:
text = RLE ( ) . decode ( text )
if use_bwt :
    text = BWT ( ) . decode ( text )
return text


signature:
def encode ( self , text ) :
    r"""Perform encoding of run - length - encoding ( RLE ) .
 Parameters
 text : str
 A text string to encode
 Returns
 str
 Word decoded by RLE
 Examples
 > > > rle = RLE ( )
 > > > bwt = BWT ( )
 > > > rle . encode ( bwt . encode ( ' align ' ) )
 ' n \ x00ilag '
 > > > rle . encode ( ' align ' )
 ' align '
 > > > rle . encode ( bwt . encode ( ' banana ' ) )
 ' annb \ x00aa '
 > > > rle . encode ( ' banana ' )
 ' banana '
 > > > rle . encode ( bwt . encode ( ' aaabaabababa ' ) )
 ' ab \ x00abbab5a '
 > > > rle . encode ( ' aaabaabababa ' )
 '3abaabababa '"""

implementation:
if text :
    text = ( ( len ( list ( g ) ) , k ) for k , g in groupby ( text ) )
    text = ( ( str ( n ) + k if n > 2 else ( k if n == 1 else 2 * k ) ) for n , k in text )
return '' . join ( text )


signature:
def decode ( self , text ) :
    r"""Perform decoding of run - length - encoding ( RLE ) .
 Parameters
 text : str
 A text string to decode
 Returns
 str
 Word decoded by RLE
 Examples
 > > > rle = RLE ( )
 > > > bwt = BWT ( )
 > > > bwt . decode ( rle . decode ( ' n \ x00ilag ' ) )
 ' align '
 > > > rle . decode ( ' align ' )
 ' align '
 > > > bwt . decode ( rle . decode ( ' annb \ x00aa ' ) )
 ' banana '
 > > > rle . decode ( ' banana ' )
 ' banana '
 > > > bwt . decode ( rle . decode ( ' ab \ x00abbab5a ' ) )
 ' aaabaabababa '
 > > > rle . decode ( ' 3abaabababa ' )
 ' aaabaabababa '"""

implementation:
mult = ''
decoded = [ ]
for letter in list ( text ) :
    if not letter . isdigit ( ) :
        if mult :
            decoded . append ( int ( mult ) * letter )
            mult = ''
        else :
            decoded . append ( letter )
    else :
        mult += letter
text = '' . join ( decoded )
return text


signature:
def encode ( self , word , max_length = 4 ) :
    """Return the SoundD code .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 4)
 Returns
 str
 The SoundD code
 Examples
 > > > sound _ d ( ' Gough ' )
 '2000'
 > > > sound _ d ( ' pneuma ' )
 '5500'
 > > > sound _ d ( ' knight ' )
 '5300'
 > > > sound _ d ( ' trice ' )
 '3620'
 > > > sound _ d ( ' judge ' )
 '2200'"""

implementation:
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = word . replace ( 'ß' , 'SS' )
word = '' . join ( c for c in word if c in self . _uc_set )
if word [ : 2 ] in { 'KN' , 'GN' , 'PN' , 'AC' , 'WR' } :
    word = word [ 1 : ]
elif word [ : 1 ] == 'X' :
    word = 'S' + word [ 1 : ]
elif word [ : 2 ] == 'WH' :
    word = 'W' + word [ 2 : ]
word = ( word . replace ( 'DGE' , '20' ) . replace ( 'DGI' , '20' ) . replace ( 'GH' , '0' ) )
word = word . translate ( self . _trans )
word = self . _delete_consecutive_repeats ( word )
word = word . replace ( '0' , '' )
if max_length != - 1 :
    if len ( word ) < max_length :
        word += '0' * ( max_length - len ( word ) )
    else :
        word = word [ : max_length ]
return word


signature:
def dist ( self , src , tar ) :
    """Return the NCD between two strings using LZMA compression .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 Returns
 float
 Compression distance
 Raises
 ValueError
 Install the PylibLZMA module in order to use LZMA
 Examples
 > > > cmp = NCDlzma ( )
 > > > cmp . dist ( ' cat ' , ' hat ' )
 0.08695652173913043
 > > > cmp . dist ( ' Niall ' , ' Neil ' )
 0.16
 > > > cmp . dist ( ' aluminum ' , ' Catalan ' )
 0.16
 > > > cmp . dist ( ' ATCG ' , ' TAGC ' )
 0.08695652173913043"""

implementation:
if src == tar :
    return 0.0
src = src . encode ( 'utf-8' )
tar = tar . encode ( 'utf-8' )
if lzma is not None :
    src_comp = lzma . compress ( src ) [ 14 : ]
    tar_comp = lzma . compress ( tar ) [ 14 : ]
    concat_comp = lzma . compress ( src + tar ) [ 14 : ]
    concat_comp2 = lzma . compress ( tar + src ) [ 14 : ]
else : # pragma : no cover
    raise ValueError ( 'Install the PylibLZMA module in order to use LZMA' )
return ( min ( len ( concat_comp ) , len ( concat_comp2 ) ) - min ( len ( src_comp ) , len ( tar_comp ) ) ) / max ( len ( src_comp ) , len ( tar_comp ) )


signature:
def smith_waterman ( src , tar , gap_cost = 1 , sim_func = sim_ident ) :
    """Return the Smith - Waterman score of two strings .
 This is a wrapper for : py : meth : ` SmithWaterman . dist _ abs ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 gap _ cost : float
 The cost of an alignment gap ( 1 by default )
 sim _ func : function
 A function that returns the similarity of two characters ( identity
 similarity by default )
 Returns
 float
 Smith - Waterman score
 Examples
 > > > smith _ waterman ( ' cat ' , ' hat ' )
 2.0
 > > > smith _ waterman ( ' Niall ' , ' Neil ' )
 1.0
 > > > smith _ waterman ( ' aluminum ' , ' Catalan ' )
 0.0
 > > > smith _ waterman ( ' ATCG ' , ' TAGC ' )
 1.0"""

implementation: return SmithWaterman ( ) . dist_abs ( src , tar , gap_cost , sim_func )


signature:
def dist_abs ( self , src , tar , gap_cost = 1 , sim_func = sim_ident ) :
    """Return the Smith - Waterman score of two strings .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 gap _ cost : float
 The cost of an alignment gap ( 1 by default )
 sim _ func : function
 A function that returns the similarity of two characters ( identity
 similarity by default )
 Returns
 float
 Smith - Waterman score
 Examples
 > > > cmp = SmithWaterman ( )
 > > > cmp . dist _ abs ( ' cat ' , ' hat ' )
 2.0
 > > > cmp . dist _ abs ( ' Niall ' , ' Neil ' )
 1.0
 > > > cmp . dist _ abs ( ' aluminum ' , ' Catalan ' )
 0.0
 > > > cmp . dist _ abs ( ' ATCG ' , ' TAGC ' )
 1.0"""

implementation:
d_mat = np_zeros ( ( len ( src ) + 1 , len ( tar ) + 1 ) , dtype = np_float32 )
for i in range ( len ( src ) + 1 ) :
    d_mat [ i , 0 ] = 0
for j in range ( len ( tar ) + 1 ) :
    d_mat [ 0 , j ] = 0
for i in range ( 1 , len ( src ) + 1 ) :
    for j in range ( 1 , len ( tar ) + 1 ) :
        match = d_mat [ i - 1 , j - 1 ] + sim_func ( src [ i - 1 ] , tar [ j - 1 ] )
        delete = d_mat [ i - 1 , j ] - gap_cost
        insert = d_mat [ i , j - 1 ] - gap_cost
        d_mat [ i , j ] = max ( 0 , match , delete , insert )
return d_mat [ d_mat . shape [ 0 ] - 1 , d_mat . shape [ 1 ] - 1 ]


signature:
def levenshtein ( src , tar , mode = 'lev' , cost = ( 1 , 1 , 1 , 1 ) ) :
    """Return the Levenshtein distance between two strings .
 This is a wrapper of : py : meth : ` Levenshtein . dist _ abs ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 mode : str
 Specifies a mode for computing the Levenshtein distance :
 - ` ` lev ` ` ( default ) computes the ordinary Levenshtein distance , in
 which edits may include inserts , deletes , and substitutions
 - ` ` osa ` ` computes the Optimal String Alignment distance , in which
 edits may include inserts , deletes , substitutions , and
 transpositions but substrings may only be edited once
 cost : tuple
 A 4 - tuple representing the cost of the four possible edits : inserts ,
 deletes , substitutions , and transpositions , respectively ( by default :
 (1 , 1 , 1 , 1 ) )
 Returns
 int ( may return a float if cost has float values )
 The Levenshtein distance between src & tar
 Examples
 > > > levenshtein ( ' cat ' , ' hat ' )
 > > > levenshtein ( ' Niall ' , ' Neil ' )
 > > > levenshtein ( ' aluminum ' , ' Catalan ' )
 > > > levenshtein ( ' ATCG ' , ' TAGC ' )
 > > > levenshtein ( ' ATCG ' , ' TAGC ' , mode = ' osa ' )
 > > > levenshtein ( ' ACTG ' , ' TAGC ' , mode = ' osa ' )"""

implementation: return Levenshtein ( ) . dist_abs ( src , tar , mode , cost )


signature:
def dist_levenshtein ( src , tar , mode = 'lev' , cost = ( 1 , 1 , 1 , 1 ) ) :
    """Return the normalized Levenshtein distance between two strings .
 This is a wrapper of : py : meth : ` Levenshtein . dist ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 mode : str
 Specifies a mode for computing the Levenshtein distance :
 - ` ` lev ` ` ( default ) computes the ordinary Levenshtein distance , in
 which edits may include inserts , deletes , and substitutions
 - ` ` osa ` ` computes the Optimal String Alignment distance , in which
 edits may include inserts , deletes , substitutions , and
 transpositions but substrings may only be edited once
 cost : tuple
 A 4 - tuple representing the cost of the four possible edits : inserts ,
 deletes , substitutions , and transpositions , respectively ( by default :
 (1 , 1 , 1 , 1 ) )
 Returns
 float
 The Levenshtein distance between src & tar
 Examples
 > > > round ( dist _ levenshtein ( ' cat ' , ' hat ' ) , 12)
 0.33333
 > > > round ( dist _ levenshtein ( ' Niall ' , ' Neil ' ) , 12)
 0.6
 > > > dist _ levenshtein ( ' aluminum ' , ' Catalan ' )
 0.875
 > > > dist _ levenshtein ( ' ATCG ' , ' TAGC ' )
 0.75"""

implementation: return Levenshtein ( ) . dist ( src , tar , mode , cost )


signature:
def sim_levenshtein ( src , tar , mode = 'lev' , cost = ( 1 , 1 , 1 , 1 ) ) :
    """Return the Levenshtein similarity of two strings .
 This is a wrapper of : py : meth : ` Levenshtein . sim ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 mode : str
 Specifies a mode for computing the Levenshtein distance :
 - ` ` lev ` ` ( default ) computes the ordinary Levenshtein distance , in
 which edits may include inserts , deletes , and substitutions
 - ` ` osa ` ` computes the Optimal String Alignment distance , in which
 edits may include inserts , deletes , substitutions , and
 transpositions but substrings may only be edited once
 cost : tuple
 A 4 - tuple representing the cost of the four possible edits : inserts ,
 deletes , substitutions , and transpositions , respectively ( by default :
 (1 , 1 , 1 , 1 ) )
 Returns
 float
 The Levenshtein similarity between src & tar
 Examples
 > > > round ( sim _ levenshtein ( ' cat ' , ' hat ' ) , 12)
 0.666667
 > > > round ( sim _ levenshtein ( ' Niall ' , ' Neil ' ) , 12)
 0.4
 > > > sim _ levenshtein ( ' aluminum ' , ' Catalan ' )
 0.125
 > > > sim _ levenshtein ( ' ATCG ' , ' TAGC ' )
 0.25"""

implementation: return Levenshtein ( ) . sim ( src , tar , mode , cost )


signature:
def dist_abs ( self , src , tar , mode = 'lev' , cost = ( 1 , 1 , 1 , 1 ) ) :
    """Return the Levenshtein distance between two strings .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 mode : str
 Specifies a mode for computing the Levenshtein distance :
 - ` ` lev ` ` ( default ) computes the ordinary Levenshtein distance ,
 in which edits may include inserts , deletes , and
 substitutions
 - ` ` osa ` ` computes the Optimal String Alignment distance , in
 which edits may include inserts , deletes , substitutions , and
 transpositions but substrings may only be edited once
 cost : tuple
 A 4 - tuple representing the cost of the four possible edits :
 inserts , deletes , substitutions , and transpositions , respectively
 ( by default : ( 1 , 1 , 1 , 1 ) )
 Returns
 int ( may return a float if cost has float values )
 The Levenshtein distance between src & tar
 Examples
 > > > cmp = Levenshtein ( )
 > > > cmp . dist _ abs ( ' cat ' , ' hat ' )
 > > > cmp . dist _ abs ( ' Niall ' , ' Neil ' )
 > > > cmp . dist _ abs ( ' aluminum ' , ' Catalan ' )
 > > > cmp . dist _ abs ( ' ATCG ' , ' TAGC ' )
 > > > cmp . dist _ abs ( ' ATCG ' , ' TAGC ' , mode = ' osa ' )
 > > > cmp . dist _ abs ( ' ACTG ' , ' TAGC ' , mode = ' osa ' )"""

implementation:
ins_cost , del_cost , sub_cost , trans_cost = cost
if src == tar :
    return 0
if not src :
    return len ( tar ) * ins_cost
if not tar :
    return len ( src ) * del_cost
d_mat = np_zeros ( ( len ( src ) + 1 , len ( tar ) + 1 ) , dtype = np_int )
for i in range ( len ( src ) + 1 ) :
    d_mat [ i , 0 ] = i * del_cost
for j in range ( len ( tar ) + 1 ) :
    d_mat [ 0 , j ] = j * ins_cost
for i in range ( len ( src ) ) :
    for j in range ( len ( tar ) ) :
        d_mat [ i + 1 , j + 1 ] = min ( d_mat [ i + 1 , j ] + ins_cost , # ins
        d_mat [ i , j + 1 ] + del_cost , # del
        d_mat [ i , j ] + ( sub_cost if src [ i ] != tar [ j ] else 0 ) , # sub / = =
        )
        if mode == 'osa' :
            if ( i + 1 > 1 and j + 1 > 1 and src [ i ] == tar [ j - 1 ] and src [ i - 1 ] == tar [ j ] ) : # transposition
                d_mat [ i + 1 , j + 1 ] = min ( d_mat [ i + 1 , j + 1 ] , d_mat [ i - 1 , j - 1 ] + trans_cost , )
return d_mat [ len ( src ) , len ( tar ) ]


signature:
def dist ( self , src , tar , mode = 'lev' , cost = ( 1 , 1 , 1 , 1 ) ) :
    """Return the normalized Levenshtein distance between two strings .
 The Levenshtein distance is normalized by dividing the Levenshtein
 distance ( calculated by any of the three supported methods ) by the
 greater of the number of characters in src times the cost of a delete
 and the number of characters in tar times the cost of an insert .
 For the case in which all operations have : math : ` cost = 1 ` , this is
 equivalent to the greater of the length of the two strings src & tar .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 mode : str
 Specifies a mode for computing the Levenshtein distance :
 - ` ` lev ` ` ( default ) computes the ordinary Levenshtein distance ,
 in which edits may include inserts , deletes , and
 substitutions
 - ` ` osa ` ` computes the Optimal String Alignment distance , in
 which edits may include inserts , deletes , substitutions , and
 transpositions but substrings may only be edited once
 cost : tuple
 A 4 - tuple representing the cost of the four possible edits :
 inserts , deletes , substitutions , and transpositions , respectively
 ( by default : ( 1 , 1 , 1 , 1 ) )
 Returns
 float
 The normalized Levenshtein distance between src & tar
 Examples
 > > > cmp = Levenshtein ( )
 > > > round ( cmp . dist ( ' cat ' , ' hat ' ) , 12)
 0.33333
 > > > round ( cmp . dist ( ' Niall ' , ' Neil ' ) , 12)
 0.6
 > > > cmp . dist ( ' aluminum ' , ' Catalan ' )
 0.875
 > > > cmp . dist ( ' ATCG ' , ' TAGC ' )
 0.75"""

implementation:
if src == tar :
    return 0
ins_cost , del_cost = cost [ : 2 ]
return levenshtein ( src , tar , mode , cost ) / ( max ( len ( src ) * del_cost , len ( tar ) * ins_cost ) )


signature:
def fingerprint ( self , word ) :
    """Return the omission key .
 Parameters
 word : str
 The word to transform into its omission key
 Returns
 str
 The omission key
 Examples
 > > > ok = OmissionKey ( )
 > > > ok . fingerprint ( ' The quick brown fox jumped over the lazy dog . ' )
 ' JKQXZVWYBFMGPDHCLNTREUIOA '
 > > > ok . fingerprint ( ' Christopher ' )
 ' PHCTSRIOE '
 > > > ok . fingerprint ( ' Niall ' )
 ' LNIA '"""

implementation:
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = '' . join ( c for c in word if c in self . _letters )
key = ''
# add consonants in order supplied by _ consonants ( no duplicates )
for char in self . _consonants :
    if char in word :
        key += char
# add vowels in order they appeared in the word ( no duplicates )
for char in word :
    if char not in self . _consonants and char not in key :
        key += char
return key


signature:
def minkowski ( src , tar , qval = 2 , pval = 1 , normalized = False , alphabet = None ) :
    """Return the Minkowski distance ( : math : ` L ^ p ` - norm ) of two strings .
 This is a wrapper for : py : meth : ` Minkowski . dist _ abs ` .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 pval : int or float
 The : math : ` p ` - value of the : math : ` L ^ p ` - space
 normalized : bool
 Normalizes to [ 0 , 1 ] if True
 alphabet : collection or int
 The values or size of the alphabet
 Returns
 float
 The Minkowski distance
 Examples
 > > > minkowski ( ' cat ' , ' hat ' )
 4.0
 > > > minkowski ( ' Niall ' , ' Neil ' )
 7.0
 > > > minkowski ( ' Colin ' , ' Cuilen ' )
 9.0
 > > > minkowski ( ' ATCG ' , ' TAGC ' )
 10.0"""

implementation: return Minkowski ( ) . dist_abs ( src , tar , qval , pval , normalized , alphabet )


signature:
def dist_minkowski ( src , tar , qval = 2 , pval = 1 , alphabet = None ) :
    """Return normalized Minkowski distance of two strings .
 This is a wrapper for : py : meth : ` Minkowski . dist ` .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 pval : int or float
 The : math : ` p ` - value of the : math : ` L ^ p ` - space
 alphabet : collection or int
 The values or size of the alphabet
 Returns
 float
 The normalized Minkowski distance
 Examples
 > > > dist _ minkowski ( ' cat ' , ' hat ' )
 0.5
 > > > round ( dist _ minkowski ( ' Niall ' , ' Neil ' ) , 12)
 0.636363636364
 > > > round ( dist _ minkowski ( ' Colin ' , ' Cuilen ' ) , 12)
 0.692307692308
 > > > dist _ minkowski ( ' ATCG ' , ' TAGC ' )
 1.0"""

implementation: return Minkowski ( ) . dist ( src , tar , qval , pval , alphabet )


signature:
def sim_minkowski ( src , tar , qval = 2 , pval = 1 , alphabet = None ) :
    """Return normalized Minkowski similarity of two strings .
 This is a wrapper for : py : meth : ` Minkowski . sim ` .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 pval : int or float
 The : math : ` p ` - value of the : math : ` L ^ p ` - space
 alphabet : collection or int
 The values or size of the alphabet
 Returns
 float
 The normalized Minkowski similarity
 Examples
 > > > sim _ minkowski ( ' cat ' , ' hat ' )
 0.5
 > > > round ( sim _ minkowski ( ' Niall ' , ' Neil ' ) , 12)
 0.363636363636
 > > > round ( sim _ minkowski ( ' Colin ' , ' Cuilen ' ) , 12)
 0.307692307692
 > > > sim _ minkowski ( ' ATCG ' , ' TAGC ' )
 0.0"""

implementation: return Minkowski ( ) . sim ( src , tar , qval , pval , alphabet )


signature:
def dist_abs ( self , src , tar , qval = 2 , pval = 1 , normalized = False , alphabet = None ) :
    """Return the Minkowski distance ( : math : ` L ^ p ` - norm ) of two strings .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 pval : int or float
 The : math : ` p ` - value of the : math : ` L ^ p ` - space
 normalized : bool
 Normalizes to [ 0 , 1 ] if True
 alphabet : collection or int
 The values or size of the alphabet
 Returns
 float
 The Minkowski distance
 Examples
 > > > cmp = Minkowski ( )
 > > > cmp . dist _ abs ( ' cat ' , ' hat ' )
 4.0
 > > > cmp . dist _ abs ( ' Niall ' , ' Neil ' )
 7.0
 > > > cmp . dist _ abs ( ' Colin ' , ' Cuilen ' )
 9.0
 > > > cmp . dist _ abs ( ' ATCG ' , ' TAGC ' )
 10.0"""

implementation:
q_src , q_tar = self . _get_qgrams ( src , tar , qval )
diffs = ( ( q_src - q_tar ) + ( q_tar - q_src ) ) . values ( )
normalizer = 1
if normalized :
    totals = ( q_src + q_tar ) . values ( )
    if alphabet is not None : # noinspection PyTypeChecker
        normalizer = ( alphabet if isinstance ( alphabet , Number ) else len ( alphabet ) )
    elif pval == 0 :
        normalizer = len ( totals )
    else :
        normalizer = sum ( _ ** pval for _ in totals ) ** ( 1 / pval )
if len ( diffs ) == 0 :
    return 0.0
if pval == float ( 'inf' ) : # Chebyshev distance
    return max ( diffs ) / normalizer
if pval == 0 : # This is the l _ 0 " norm " as developed by David Donoho
    return len ( diffs ) / normalizer
return sum ( _ ** pval for _ in diffs ) ** ( 1 / pval ) / normalizer


signature:
def dist ( self , src , tar , qval = 2 , pval = 1 , alphabet = None ) :
    """Return normalized Minkowski distance of two strings .
 The normalized Minkowski distance : cite : ` Minkowski : 1910 ` is a distance
 metric in : math : ` L ^ p ` - space , normalized to [ 0 , 1 ] .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 pval : int or float
 The : math : ` p ` - value of the : math : ` L ^ p ` - space
 alphabet : collection or int
 The values or size of the alphabet
 Returns
 float
 The normalized Minkowski distance
 Examples
 > > > cmp = Minkowski ( )
 > > > cmp . dist ( ' cat ' , ' hat ' )
 0.5
 > > > round ( cmp . dist ( ' Niall ' , ' Neil ' ) , 12)
 0.636363636364
 > > > round ( cmp . dist ( ' Colin ' , ' Cuilen ' ) , 12)
 0.692307692308
 > > > cmp . dist ( ' ATCG ' , ' TAGC ' )
 1.0"""

implementation: return self . dist_abs ( src , tar , qval , pval , True , alphabet )


signature:
def occurrence_halved_fingerprint ( word , n_bits = 16 , most_common = MOST_COMMON_LETTERS_CG ) :
    """Return the occurrence halved fingerprint .
 This is a wrapper for : py : meth : ` OccurrenceHalved . fingerprint ` .
 Parameters
 word : str
 The word to fingerprint
 n _ bits : int
 Number of bits in the fingerprint returned
 most _ common : list
 The most common tokens in the target language , ordered by frequency
 Returns
 int
 The occurrence halved fingerprint
 Examples
 > > > bin ( occurrence _ halved _ fingerprint ( ' hat ' ) )
 '0b1010000010'
 > > > bin ( occurrence _ halved _ fingerprint ( ' niall ' ) )
 '0b10010100000'
 > > > bin ( occurrence _ halved _ fingerprint ( ' colin ' ) )
 '0b1001010000'
 > > > bin ( occurrence _ halved _ fingerprint ( ' atcg ' ) )
 '0b10100000'
 > > > bin ( occurrence _ halved _ fingerprint ( ' entreatment ' ) )
 '0b1111010000110000'"""

implementation: return OccurrenceHalved ( ) . fingerprint ( word , n_bits , most_common )


signature:
def fingerprint ( self , word , n_bits = 16 , most_common = MOST_COMMON_LETTERS_CG ) :
    """Return the occurrence halved fingerprint .
 Based on the occurrence halved fingerprint from : cite : ` Cislak : 2017 ` .
 Parameters
 word : str
 The word to fingerprint
 n _ bits : int
 Number of bits in the fingerprint returned
 most _ common : list
 The most common tokens in the target language , ordered by frequency
 Returns
 int
 The occurrence halved fingerprint
 Examples
 > > > ohf = OccurrenceHalved ( )
 > > > bin ( ohf . fingerprint ( ' hat ' ) )
 '0b1010000010'
 > > > bin ( ohf . fingerprint ( ' niall ' ) )
 '0b10010100000'
 > > > bin ( ohf . fingerprint ( ' colin ' ) )
 '0b1001010000'
 > > > bin ( ohf . fingerprint ( ' atcg ' ) )
 '0b10100000'
 > > > bin ( ohf . fingerprint ( ' entreatment ' ) )
 '0b1111010000110000'"""

implementation:
if n_bits % 2 :
    n_bits += 1
w_len = len ( word ) // 2
w_1 = set ( word [ : w_len ] )
w_2 = set ( word [ w_len : ] )
fingerprint = 0
for letter in most_common :
    if n_bits :
        fingerprint <<= 1
        if letter in w_1 :
            fingerprint += 1
        fingerprint <<= 1
        if letter in w_2 :
            fingerprint += 1
        n_bits -= 2
    else :
        break
if n_bits > 0 :
    fingerprint <<= n_bits
return fingerprint


signature:
def encode ( self , word , max_length = 3 ) :
    """Calculate the early version of the Henry code for a word .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 3)
 Returns
 str
 The early Henry code
 Examples
 > > > henry _ early ( ' Marchand ' )
 ' MRC '
 > > > henry _ early ( ' Beaulieu ' )
 ' BL '
 > > > henry _ early ( ' Beaumont ' )
 ' BM '
 > > > henry _ early ( ' Legrand ' )
 ' LGR '
 > > > henry _ early ( ' Pelletier ' )
 ' PLT '"""

implementation:
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = '' . join ( c for c in word if c in self . _uc_set )
if not word :
    return ''
# Rule Ia seems to be covered entirely in II
# Rule Ib
if word [ 0 ] in self . _uc_vy_set : # Ib1
    if ( word [ 1 : 2 ] in self . _uc_c_set - { 'M' , 'N' } and word [ 2 : 3 ] in self . _uc_c_set ) or ( word [ 1 : 2 ] in self . _uc_c_set and word [ 2 : 3 ] not in self . _uc_c_set ) :
        if word [ 0 ] == 'Y' :
            word = 'I' + word [ 1 : ]
    # Ib2
    elif word [ 1 : 2 ] in { 'M' , 'N' } and word [ 2 : 3 ] in self . _uc_c_set :
        if word [ 0 ] == 'E' :
            word = 'A' + word [ 1 : ]
        elif word [ 0 ] in { 'I' , 'U' , 'Y' } :
            word = 'E' + word [ 1 : ]
    # Ib3
    elif word [ : 2 ] in self . _diph :
        word = self . _diph [ word [ : 2 ] ] + word [ 2 : ]
    # Ib4
    elif word [ 1 : 2 ] in self . _uc_vy_set and word [ 0 ] == 'Y' :
        word = 'I' + word [ 1 : ]
code = ''
skip = 0
# Rule II
for pos , char in enumerate ( word ) :
    nxch = word [ pos + 1 : pos + 2 ]
    prev = word [ pos - 1 : pos ]
    if skip :
        skip -= 1
    elif char in self . _uc_vy_set :
        code += char
    # IIc
    elif char == nxch :
        skip = 1
        code += char
    elif word [ pos : pos + 2 ] in { 'CQ' , 'DT' , 'SC' } :
        continue
    # IIb
    elif char in self . _simple :
        code += self . _simple [ char ]
    elif char in { 'C' , 'G' , 'P' , 'Q' , 'S' } :
        if char == 'C' :
            if nxch in { 'A' , 'O' , 'U' , 'L' , 'R' } :
                code += 'K'
            elif nxch in { 'E' , 'I' , 'Y' } :
                code += 'S'
            elif nxch == 'H' :
                if word [ pos + 2 : pos + 3 ] in self . _uc_vy_set :
                    code += 'C'
                else : # CHR , CHL , etc .
                    code += 'K'
            else :
                code += 'C'
        elif char == 'G' :
            if nxch in { 'A' , 'O' , 'U' , 'L' , 'R' } :
                code += 'G'
            elif nxch in { 'E' , 'I' , 'Y' } :
                code += 'J'
            elif nxch == 'N' :
                code += 'N'
        elif char == 'P' :
            if nxch != 'H' :
                code += 'P'
            else :
                code += 'F'
        elif char == 'Q' :
            if word [ pos + 1 : pos + 3 ] in { 'UE' , 'UI' , 'UY' } :
                code += 'G'
            else : # QUA , QUO , etc .
                code += 'K'
        else :
            if word [ pos : pos + 6 ] == 'SAINTE' :
                code += 'X'
                skip = 5
            elif word [ pos : pos + 5 ] == 'SAINT' :
                code += 'X'
                skip = 4
            elif word [ pos : pos + 3 ] == 'STE' :
                code += 'X'
                skip = 2
            elif word [ pos : pos + 2 ] == 'ST' :
                code += 'X'
                skip = 1
            elif nxch in self . _uc_c_set :
                continue
            else :
                code += 'S'
    # IId
    elif char == 'H' and prev in self . _uc_c_set :
        continue
    elif char in self . _uc_c_set - { 'L' , 'R' , } and nxch in self . _uc_c_set - { 'L' , 'R' } :
        continue
    elif char == 'L' and nxch in { 'M' , 'N' } :
        continue
    elif ( char in { 'M' , 'N' } and prev in self . _uc_vy_set and nxch in self . _uc_c_set ) :
        continue
    # IIa
    else :
        code += char
# IIe1
if code [ - 4 : ] in { 'AULT' , 'EULT' , 'OULT' } :
    code = code [ : - 2 ]
# The following are blocked by rules above
# elif code [ - 4 : - 3 ] in _ vows and code [ - 3 : ] = = ' MPS ' :
# code = code [ : - 3]
# elif code [ - 3 : - 2 ] in _ vows and code [ - 2 : ] in { ' MB ' , ' MP ' , ' ND ' ,
# ' NS ' , ' NT ' } :
# code = code [ : - 2]
elif code [ - 2 : - 1 ] == 'R' and code [ - 1 : ] in self . _uc_c_set :
    code = code [ : - 1 ]
# IIe2
elif code [ - 2 : - 1 ] in self . _uc_vy_set and code [ - 1 : ] in { 'D' , 'M' , 'N' , 'S' , 'T' , } :
    code = code [ : - 1 ]
elif code [ - 2 : ] == 'ER' :
    code = code [ : - 1 ]
# Drop non - initial vowels
code = code [ : 1 ] + code [ 1 : ] . translate ( { 65 : '' , 69 : '' , 73 : '' , 79 : '' , 85 : '' , 89 : '' } )
if max_length != - 1 :
    code = code [ : max_length ]
return code


signature:
def pshp_soundex_first ( fname , max_length = 4 , german = False ) :
    """Calculate the PSHP Soundex / Viewex Coding of a first name .
 This is a wrapper for : py : meth : ` PSHPSoundexFirst . encode ` .
 Parameters
 fname : str
 The first name to encode
 max _ length : int
 The length of the code returned ( defaults to 4)
 german : bool
 Set to True if the name is German ( different rules apply )
 Returns
 str
 The PSHP Soundex / Viewex Coding
 Examples
 > > > pshp _ soundex _ first ( ' Smith ' )
 ' S530'
 > > > pshp _ soundex _ first ( ' Waters ' )
 ' W352'
 > > > pshp _ soundex _ first ( ' James ' )
 ' J700'
 > > > pshp _ soundex _ first ( ' Schmidt ' )
 ' S500'
 > > > pshp _ soundex _ first ( ' Ashcroft ' )
 ' A220'
 > > > pshp _ soundex _ first ( ' John ' )
 ' J500'
 > > > pshp _ soundex _ first ( ' Colin ' )
 ' K400'
 > > > pshp _ soundex _ first ( ' Niall ' )
 ' N400'
 > > > pshp _ soundex _ first ( ' Sally ' )
 ' S400'
 > > > pshp _ soundex _ first ( ' Jane ' )
 ' J500'"""

implementation: return PSHPSoundexFirst ( ) . encode ( fname , max_length , german )


signature:
def encode ( self , fname , max_length = 4 , german = False ) :
    """Calculate the PSHP Soundex / Viewex Coding of a first name .
 Parameters
 fname : str
 The first name to encode
 max _ length : int
 The length of the code returned ( defaults to 4)
 german : bool
 Set to True if the name is German ( different rules apply )
 Returns
 str
 The PSHP Soundex / Viewex Coding
 Examples
 > > > pe = PSHPSoundexFirst ( )
 > > > pe . encode ( ' Smith ' )
 ' S530'
 > > > pe . encode ( ' Waters ' )
 ' W352'
 > > > pe . encode ( ' James ' )
 ' J700'
 > > > pe . encode ( ' Schmidt ' )
 ' S500'
 > > > pe . encode ( ' Ashcroft ' )
 ' A220'
 > > > pe . encode ( ' John ' )
 ' J500'
 > > > pe . encode ( ' Colin ' )
 ' K400'
 > > > pe . encode ( ' Niall ' )
 ' N400'
 > > > pe . encode ( ' Sally ' )
 ' S400'
 > > > pe . encode ( ' Jane ' )
 ' J500'"""

implementation:
fname = unicode_normalize ( 'NFKD' , text_type ( fname . upper ( ) ) )
fname = fname . replace ( 'ß' , 'SS' )
fname = '' . join ( c for c in fname if c in self . _uc_set )
# special rules
if fname == 'JAMES' :
    code = 'J7'
elif fname == 'PAT' :
    code = 'P7'
else : # A . Prefix treatment
    if fname [ : 2 ] in { 'GE' , 'GI' , 'GY' } :
        fname = 'J' + fname [ 1 : ]
    elif fname [ : 2 ] in { 'CE' , 'CI' , 'CY' } :
        fname = 'S' + fname [ 1 : ]
    elif fname [ : 3 ] == 'CHR' :
        fname = 'K' + fname [ 1 : ]
    elif fname [ : 1 ] == 'C' and fname [ : 2 ] != 'CH' :
        fname = 'K' + fname [ 1 : ]
    if fname [ : 2 ] == 'KN' :
        fname = 'N' + fname [ 1 : ]
    elif fname [ : 2 ] == 'PH' :
        fname = 'F' + fname [ 1 : ]
    elif fname [ : 3 ] in { 'WIE' , 'WEI' } :
        fname = 'V' + fname [ 1 : ]
    if german and fname [ : 1 ] in { 'W' , 'M' , 'Y' , 'Z' } :
        fname = { 'W' : 'V' , 'M' : 'N' , 'Y' : 'J' , 'Z' : 'S' } [ fname [ 0 ] ] + fname [ 1 : ]
    code = fname [ : 1 ]
    # B . Soundex coding
    # code for Y unspecified , but presumably is 0
    fname = fname . translate ( self . _trans )
    fname = self . _delete_consecutive_repeats ( fname )
    code += fname [ 1 : ]
    syl_ptr = code . find ( '0' )
    syl2_ptr = code [ syl_ptr + 1 : ] . find ( '0' )
    if syl_ptr != - 1 and syl2_ptr != - 1 and syl2_ptr - syl_ptr > - 1 :
        code = code [ : syl_ptr + 2 ]
    code = code . replace ( '0' , '' )
# rule 1
if max_length != - 1 :
    if len ( code ) < max_length :
        code += '0' * ( max_length - len ( code ) )
    else :
        code = code [ : max_length ]
return code


signature:
def c2u ( name ) :
    """Convert camelCase ( used in PHP ) to Python - standard snake _ case .
 Src :
 https : / / stackoverflow . com / questions / 1175208 / elegant - python - function - to - convert - camelcase - to - snake - case
 Parameters
 name : A function or variable name in camelCase
 Returns
 str : The name in snake _ case"""


signature:
def pythonize ( line , fn = '' , subdir = 'gen' ) :
    """Convert a line of BMPM code from PHP to Python .
 Parameters
 line : str
 A line of code
 fn : str
 A filename
 subdir : str
 The file ' s subdirectory
 Returns
 The code in Python"""

implementation:
global array_seen , nl , sd
if '$all' in line :
    return ''
if 'make the sum of all languages be visible in the function' in line :
    return ''
line = line . strip ( )
if 'array' in line and not line . startswith ( '//' ) :
    array_seen = True
line = re . sub ( '//+' , '#' , line )
# line = re . sub ( ' " \ . \ ( ( \ $ . + ? ) \ ) \ . " ' , r ' \ 1 ' , line )
if line and re . search ( r'array\("[^"]+?"\)' , line ) : # print ( " # # # " + line )
    line = ''
line = line . replace ( 'array' , '' )
line = re . sub ( r'^\s*' , '' , line )
line = re . sub ( ';$' , '' , line )
line = re . sub ( '^include_.+' , '' , line )
line = re . sub ( r'\$(approx|rules|exact)\[LanguageIndex\("([^"]+)", ' + r'\$languages\)\] = \$([a-zA-Z]+)' , lambda m : ( "BMDATA['" + subdir + "']['" + m . group ( 1 ) + "'][L_" + m . group ( 2 ) . upper ( ) + '] = _' + subdir . upper ( ) + '_' + c2u ( m . group ( 3 ) ) . upper ( ) ) , line , )
line = re . sub ( r'\$(approx|rules|exact|hebrew)([A-Za-z]+) = _merge' + r'\(\$([a-zA-Z]+), \$([a-zA-Z]+)\)' , lambda m : ( "BMDATA['" + subdir + "']['" + m . group ( 1 ) + "'][L_" + c2u ( m . group ( 2 ) ) . upper ( ) + '] = _' + subdir . upper ( ) + '_' + c2u ( m . group ( 3 ) ) . upper ( ) + ' + _' + subdir . upper ( ) + '_' + c2u ( m . group ( 4 ) ) . upper ( ) ) , line , )
line = re . sub ( r'\$(approx|rules|exact)\[LanguageIndex\("([^"]+)", ' + r'\$languages\)\] = _merge\(\$([a-zA-Z]+), \$([a-zA-Z]+)\)' , lambda m : ( "BMDATA['" + subdir + "']['" + m . group ( 1 ) + "'][L_" + c2u ( m . group ( 2 ) ) . upper ( ) + '] = _' + subdir . upper ( ) + '_' + c2u ( m . group ( 3 ) ) . upper ( ) + ' + _' + subdir . upper ( ) + '_' + c2u ( m . group ( 4 ) ) . upper ( ) ) , line , )
line = re . sub ( r'^\$([a-zA-Z]+)' , lambda m : '_' + sd . upper ( ) + '_' + c2u ( m . group ( 1 ) ) . upper ( ) , line , )
for _ in range ( len ( lang_tuple ) ) :
    line = re . sub ( r'($[a-zA-Z]+) *\+ *($[a-zA-Z]+)' , r'\1\+\2' , line )
line = re . sub ( r'\$([a-zA-Z]+)' , lambda m : ( 'L_' + m . group ( 1 ) . upper ( ) if m . group ( 1 ) in lang_dict else '$' + m . group ( 1 ) ) , line , )
line = re . sub ( r'\[\"\.\((L_[A-Z_+]+)\)\.\"\]' , r'[\1]' , line )
line = re . sub ( 'L_([A-Z]+)' , lambda m : str ( lang_dict [ m . group ( 1 ) . lower ( ) ] ) , line )
for _ in range ( 4 ) :
    line = re . sub ( r'([0-9]+) *\+ *([0-9]+)' , lambda m : str ( int ( m . group ( 1 ) ) + int ( m . group ( 2 ) ) ) , line , )
if fn == 'lang' :
    if len ( line . split ( ',' ) ) >= 3 :
        parts = line . split ( ',' )
        parts [ 0 ] = re . sub ( '/(.+?)/' , r'\1' , parts [ 0 ] )
        # parts [ 1 ] = re . sub ( ' \ $ ' , ' L _ ' , parts [ 1 ] )
        # parts [ 1 ] = re . sub ( ' * \ + * ' , ' | ' , parts [ 1 ] )
        parts [ 2 ] = parts [ 2 ] . title ( )
        line = ',' . join ( parts )
if 'languagenames' in fn :
    line = line . replace ( '"' , "'" )
    line = line . replace ( "','" , "', '" )
    if line and line [ 0 ] == "'" :
        line = ' ' * 14 + line
# fix upstream
# line = line . replace ( ' ë ' , ' ü ' )
comment = ''
if '#' in line :
    hashsign = line . find ( '#' )
    comment = line [ hashsign : ]
    code = line [ : hashsign ]
else :
    code = line
code = code . rstrip ( )
comment = comment . strip ( )
if not re . match ( r'^\s*$' , code ) :
    comment = '  ' + comment
if '(' in code and ')' in code :
    prefix = code [ : code . find ( '(' ) + 1 ]
    suffix = code [ code . rfind ( ')' ) : ]
    tuplecontent = code [ len ( prefix ) : len ( code ) - len ( suffix ) ]
    elts = tuplecontent . split ( ',' )
    for i in range ( len ( elts ) ) :
        elts [ i ] = elts [ i ] . strip ( )
        if elts [ i ] [ 0 ] == '"' and elts [ i ] [ - 1 ] == '"' :
            elts [ i ] = "'" + elts [ i ] [ 1 : - 1 ] . replace ( "'" , "\\'" ) + "'"
    tuplecontent = ', ' . join ( elts )
    code = prefix + tuplecontent + suffix
line = code + comment
line = re . sub ( '# *' , '# ' , line )
if line :
    nl = False
    if array_seen and not ( line [ 0 ] == '_' or line . startswith ( 'BMDATA' ) ) :
        line = ' ' * 4 + line
    return line + '\n'
elif not nl :
    nl = True
    return '\n'
else :
    return ''


signature:
def sim ( self , src , tar , qval = 2 ) :
    r"""Return the cosine similarity of two strings .
 Parameters
 src : str
 Source string ( or QGrams / Counter objects ) for comparison
 tar : str
 Target string ( or QGrams / Counter objects ) for comparison
 qval : int
 The length of each q - gram ; 0 for non - q - gram version
 Returns
 float
 Cosine similarity
 Examples
 > > > cmp = Cosine ( )
 > > > cmp . sim ( ' cat ' , ' hat ' )
 0.5
 > > > cmp . sim ( ' Niall ' , ' Neil ' )
 0.3651483716701107
 > > > cmp . sim ( ' aluminum ' , ' Catalan ' )
 0.11785113019775793
 > > > cmp . sim ( ' ATCG ' , ' TAGC ' )
 0.0"""

implementation:
if src == tar :
    return 1.0
if not src or not tar :
    return 0.0
q_src , q_tar = self . _get_qgrams ( src , tar , qval )
q_src_mag = sum ( q_src . values ( ) )
q_tar_mag = sum ( q_tar . values ( ) )
q_intersection_mag = sum ( ( q_src & q_tar ) . values ( ) )
return q_intersection_mag / sqrt ( q_src_mag * q_tar_mag )


signature:
def sim_monge_elkan ( src , tar , sim_func = sim_levenshtein , symmetric = False ) :
    """Return the Monge - Elkan similarity of two strings .
 This is a wrapper for : py : meth : ` MongeElkan . sim ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 sim _ func : function
 Rhe internal similarity metric to employ
 symmetric : bool
 Return a symmetric similarity measure
 Returns
 float
 Monge - Elkan similarity
 Examples
 > > > sim _ monge _ elkan ( ' cat ' , ' hat ' )
 0.75
 > > > round ( sim _ monge _ elkan ( ' Niall ' , ' Neil ' ) , 12)
 0.666667
 > > > round ( sim _ monge _ elkan ( ' aluminum ' , ' Catalan ' ) , 12)
 0.3888889
 > > > sim _ monge _ elkan ( ' ATCG ' , ' TAGC ' )
 0.5"""

implementation: return MongeElkan ( ) . sim ( src , tar , sim_func , symmetric )


signature:
def dist_monge_elkan ( src , tar , sim_func = sim_levenshtein , symmetric = False ) :
    """Return the Monge - Elkan distance between two strings .
 This is a wrapper for : py : meth : ` MongeElkan . dist ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 sim _ func : function
 The internal similarity metric to employ
 symmetric : bool
 Return a symmetric similarity measure
 Returns
 float
 Monge - Elkan distance
 Examples
 > > > dist _ monge _ elkan ( ' cat ' , ' hat ' )
 0.25
 > > > round ( dist _ monge _ elkan ( ' Niall ' , ' Neil ' ) , 12)
 0.33333
 > > > round ( dist _ monge _ elkan ( ' aluminum ' , ' Catalan ' ) , 12)
 0.611111
 > > > dist _ monge _ elkan ( ' ATCG ' , ' TAGC ' )
 0.5"""

implementation: return MongeElkan ( ) . dist ( src , tar , sim_func , symmetric )


signature:
def sim ( self , src , tar , sim_func = sim_levenshtein , symmetric = False ) :
    """Return the Monge - Elkan similarity of two strings .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 sim _ func : function
 The internal similarity metric to employ
 symmetric : bool
 Return a symmetric similarity measure
 Returns
 float
 Monge - Elkan similarity
 Examples
 > > > cmp = MongeElkan ( )
 > > > cmp . sim ( ' cat ' , ' hat ' )
 0.75
 > > > round ( cmp . sim ( ' Niall ' , ' Neil ' ) , 12)
 0.666667
 > > > round ( cmp . sim ( ' aluminum ' , ' Catalan ' ) , 12)
 0.3888889
 > > > cmp . sim ( ' ATCG ' , ' TAGC ' )
 0.5"""

implementation:
if src == tar :
    return 1.0
q_src = sorted ( QGrams ( src ) . elements ( ) )
q_tar = sorted ( QGrams ( tar ) . elements ( ) )
if not q_src or not q_tar :
    return 0.0
sum_of_maxes = 0
for q_s in q_src :
    max_sim = float ( '-inf' )
    for q_t in q_tar :
        max_sim = max ( max_sim , sim_func ( q_s , q_t ) )
    sum_of_maxes += max_sim
sim_em = sum_of_maxes / len ( q_src )
if symmetric :
    sim_em = ( sim_em + self . sim ( tar , src , sim_func , False ) ) / 2
return sim_em


signature:
def encode ( self , word ) :
    """Return the Phonem code for a word .
 Parameters
 word : str
 The word to transform
 Returns
 str
 The Phonem value
 Examples
 > > > pe = Phonem ( )
 > > > pe . encode ( ' Christopher ' )
 ' CRYSDOVR '
 > > > pe . encode ( ' Niall ' )
 ' NYAL '
 > > > pe . encode ( ' Smith ' )
 ' SMYD '
 > > > pe . encode ( ' Schmidt ' )
 ' CMYD '"""

implementation:
word = unicode_normalize ( 'NFC' , text_type ( word . upper ( ) ) )
for i , j in self . _substitutions :
    word = word . replace ( i , j )
word = word . translate ( self . _trans )
return '' . join ( c for c in self . _delete_consecutive_repeats ( word ) if c in self . _uc_set )


signature:
def stem ( self , word ) :
    """Return CLEF Swedish stem .
 Parameters
 word : str
 The word to stem
 Returns
 str
 Word stem
 Examples
 > > > clef _ swedish ( ' undervisa ' )
 ' undervis '
 > > > clef _ swedish ( ' suspension ' )
 ' suspensio '
 > > > clef _ swedish ( ' visshet ' )
 ' viss '"""

implementation:
wlen = len ( word ) - 2
if wlen > 2 and word [ - 1 ] == 's' :
    word = word [ : - 1 ]
    wlen -= 1
_endings = { 5 : { 'elser' , 'heten' } , 4 : { 'arne' , 'erna' , 'ande' , 'else' , 'aste' , 'orna' , 'aren' } , 3 : { 'are' , 'ast' , 'het' } , 2 : { 'ar' , 'er' , 'or' , 'en' , 'at' , 'te' , 'et' } , 1 : { 'a' , 'e' , 'n' , 't' } , }
for end_len in range ( 5 , 0 , - 1 ) :
    if wlen > end_len and word [ - end_len : ] in _endings [ end_len ] :
        return word [ : - end_len ]
return word


signature:
def _undouble ( self , word ) :
    """Undouble endings - kk , - dd , and - tt .
 Parameters
 word : str
 The word to stem
 Returns
 str
 The word with doubled endings undoubled"""

implementation:
if ( len ( word ) > 1 and word [ - 1 ] == word [ - 2 ] and word [ - 1 ] in { 'd' , 'k' , 't' } ) :
    return word [ : - 1 ]
return word


signature:
def stem ( self , word ) :
    """Return Snowball Dutch stem .
 Parameters
 word : str
 The word to stem
 Returns
 str
 Word stem
 Examples
 > > > stmr = SnowballDutch ( )
 > > > stmr . stem ( ' lezen ' )
 ' lez '
 > > > stmr . stem ( ' opschorting ' )
 ' opschort '
 > > > stmr . stem ( ' ongrijpbaarheid ' )
 ' ongrijp '"""

implementation:
# lowercase , normalize , decompose , filter umlauts & acutes out , and
# compose
word = normalize ( 'NFC' , text_type ( word . lower ( ) ) )
word = word . translate ( self . _accented )
for i in range ( len ( word ) ) :
    if i == 0 and word [ 0 ] == 'y' :
        word = 'Y' + word [ 1 : ]
    elif word [ i ] == 'y' and word [ i - 1 ] in self . _vowels :
        word = word [ : i ] + 'Y' + word [ i + 1 : ]
    elif ( word [ i ] == 'i' and word [ i - 1 ] in self . _vowels and i + 1 < len ( word ) and word [ i + 1 ] in self . _vowels ) :
        word = word [ : i ] + 'I' + word [ i + 1 : ]
r1_start = max ( 3 , self . _sb_r1 ( word ) )
r2_start = self . _sb_r2 ( word )
# Step 1
if word [ - 5 : ] == 'heden' :
    if len ( word [ r1_start : ] ) >= 5 :
        word = word [ : - 3 ] + 'id'
elif word [ - 3 : ] == 'ene' :
    if len ( word [ r1_start : ] ) >= 3 and ( word [ - 4 ] not in self . _vowels and word [ - 6 : - 3 ] != 'gem' ) :
        word = self . _undouble ( word [ : - 3 ] )
elif word [ - 2 : ] == 'en' :
    if len ( word [ r1_start : ] ) >= 2 and ( word [ - 3 ] not in self . _vowels and word [ - 5 : - 2 ] != 'gem' ) :
        word = self . _undouble ( word [ : - 2 ] )
elif word [ - 2 : ] == 'se' :
    if ( len ( word [ r1_start : ] ) >= 2 and word [ - 3 ] not in self . _not_s_endings ) :
        word = word [ : - 2 ]
elif word [ - 1 : ] == 's' :
    if ( len ( word [ r1_start : ] ) >= 1 and word [ - 2 ] not in self . _not_s_endings ) :
        word = word [ : - 1 ]
# Step 2
e_removed = False
if word [ - 1 : ] == 'e' :
    if len ( word [ r1_start : ] ) >= 1 and word [ - 2 ] not in self . _vowels :
        word = self . _undouble ( word [ : - 1 ] )
        e_removed = True
# Step 3a
if word [ - 4 : ] == 'heid' :
    if len ( word [ r2_start : ] ) >= 4 and word [ - 5 ] != 'c' :
        word = word [ : - 4 ]
        if word [ - 2 : ] == 'en' :
            if len ( word [ r1_start : ] ) >= 2 and ( word [ - 3 ] not in self . _vowels and word [ - 5 : - 2 ] != 'gem' ) :
                word = self . _undouble ( word [ : - 2 ] )
# Step 3b
if word [ - 4 : ] == 'lijk' :
    if len ( word [ r2_start : ] ) >= 4 :
        word = word [ : - 4 ]
        # Repeat step 2
        if word [ - 1 : ] == 'e' :
            if ( len ( word [ r1_start : ] ) >= 1 and word [ - 2 ] not in self . _vowels ) :
                word = self . _undouble ( word [ : - 1 ] )
elif word [ - 4 : ] == 'baar' :
    if len ( word [ r2_start : ] ) >= 4 :
        word = word [ : - 4 ]
elif word [ - 3 : ] in ( 'end' , 'ing' ) :
    if len ( word [ r2_start : ] ) >= 3 :
        word = word [ : - 3 ]
        if ( word [ - 2 : ] == 'ig' and len ( word [ r2_start : ] ) >= 2 and word [ - 3 ] != 'e' ) :
            word = word [ : - 2 ]
        else :
            word = self . _undouble ( word )
elif word [ - 3 : ] == 'bar' :
    if len ( word [ r2_start : ] ) >= 3 and e_removed :
        word = word [ : - 3 ]
elif word [ - 2 : ] == 'ig' :
    if len ( word [ r2_start : ] ) >= 2 and word [ - 3 ] != 'e' :
        word = word [ : - 2 ]
# Step 4
if ( len ( word ) >= 4 and word [ - 3 ] == word [ - 2 ] and word [ - 2 ] in { 'a' , 'e' , 'o' , 'u' } and word [ - 4 ] not in self . _vowels and word [ - 1 ] not in self . _vowels and word [ - 1 ] != 'I' ) :
    word = word [ : - 2 ] + word [ - 1 ]
# Change ' Y ' and ' U ' back to lowercase if survived stemming
for i in range ( 0 , len ( word ) ) :
    if word [ i ] == 'Y' :
        word = word [ : i ] + 'y' + word [ i + 1 : ]
    elif word [ i ] == 'I' :
        word = word [ : i ] + 'i' + word [ i + 1 : ]
return word


signature:
def soundex ( word , max_length = 4 , var = 'American' , reverse = False , zero_pad = True ) :
    """Return the Soundex code for a word .
 This is a wrapper for : py : meth : ` Soundex . encode ` .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 4)
 var : str
 The variant of the algorithm to employ ( defaults to ` ` American ` ` ) :
 - ` ` American ` ` follows the American Soundex algorithm , as described
 at : cite : ` US : 2007 ` and in : cite : ` Knuth : 1998 ` ; this is also called
 Miracode
 - ` ` special ` ` follows the rules from the 1880-1910 US Census
 retrospective re - analysis , in which h & w are not treated as
 blocking consonants but as vowels . Cf . : cite : ` Repici : 2013 ` .
 - ` ` Census ` ` follows the rules laid out in GIL 55 : cite : ` US : 1997 `
 by the US Census , including coding prefixed and unprefixed
 versions of some names
 reverse : bool
 Reverse the word before computing the selected Soundex ( defaults to
 False ) ; This results in " Reverse Soundex " , which is useful for blocking
 in cases where the initial elements may be in error .
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length string
 Returns
 str
 The Soundex value
 Examples
 > > > soundex ( " Christopher " )
 ' C623'
 > > > soundex ( " Niall " )
 ' N400'
 > > > soundex ( ' Smith ' )
 ' S530'
 > > > soundex ( ' Schmidt ' )
 ' S530'
 > > > soundex ( ' Christopher ' , max _ length = - 1)
 ' C6231600000'
 > > > soundex ( ' Christopher ' , max _ length = - 1 , zero _ pad = False )
 ' C62316'
 > > > soundex ( ' Christopher ' , reverse = True )
 ' R132'
 > > > soundex ( ' Ashcroft ' )
 ' A261'
 > > > soundex ( ' Asicroft ' )
 ' A226'
 > > > soundex ( ' Ashcroft ' , var = ' special ' )
 ' A226'
 > > > soundex ( ' Asicroft ' , var = ' special ' )
 ' A226'"""

implementation: return Soundex ( ) . encode ( word , max_length , var , reverse , zero_pad )


signature:
def encode ( self , word , max_length = 4 , var = 'American' , reverse = False , zero_pad = True ) :
    """Return the Soundex code for a word .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 4)
 var : str
 The variant of the algorithm to employ ( defaults to ` ` American ` ` ) :
 - ` ` American ` ` follows the American Soundex algorithm , as
 described at : cite : ` US : 2007 ` and in : cite : ` Knuth : 1998 ` ; this
 is also called Miracode
 - ` ` special ` ` follows the rules from the 1880-1910 US Census
 retrospective re - analysis , in which h & w are not treated as
 blocking consonants but as vowels . Cf . : cite : ` Repici : 2013 ` .
 - ` ` Census ` ` follows the rules laid out in GIL 55
 : cite : ` US : 1997 ` by the US Census , including coding prefixed
 and unprefixed versions of some names
 reverse : bool
 Reverse the word before computing the selected Soundex ( defaults to
 False ) ; This results in " Reverse Soundex " , which is useful for
 blocking in cases where the initial elements may be in error .
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length
 string
 Returns
 str
 The Soundex value
 Examples
 > > > pe = Soundex ( )
 > > > pe . encode ( " Christopher " )
 ' C623'
 > > > pe . encode ( " Niall " )
 ' N400'
 > > > pe . encode ( ' Smith ' )
 ' S530'
 > > > pe . encode ( ' Schmidt ' )
 ' S530'
 > > > pe . encode ( ' Christopher ' , max _ length = - 1)
 ' C6231600000'
 > > > pe . encode ( ' Christopher ' , max _ length = - 1 , zero _ pad = False )
 ' C62316'
 > > > pe . encode ( ' Christopher ' , reverse = True )
 ' R132'
 > > > pe . encode ( ' Ashcroft ' )
 ' A261'
 > > > pe . encode ( ' Asicroft ' )
 ' A226'
 > > > pe . encode ( ' Ashcroft ' , var = ' special ' )
 ' A226'
 > > > pe . encode ( ' Asicroft ' , var = ' special ' )
 ' A226'"""

implementation:
# Require a max _ length of at least 4 and not more than 64
if max_length != - 1 :
    max_length = min ( max ( 4 , max_length ) , 64 )
else :
    max_length = 64
# uppercase , normalize , decompose , and filter non - A - Z out
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = word . replace ( 'ß' , 'SS' )
if var == 'Census' :
    if word [ : 3 ] in { 'VAN' , 'CON' } and len ( word ) > 4 :
        return ( soundex ( word , max_length , 'American' , reverse , zero_pad ) , soundex ( word [ 3 : ] , max_length , 'American' , reverse , zero_pad ) , )
    if word [ : 2 ] in { 'DE' , 'DI' , 'LA' , 'LE' } and len ( word ) > 3 :
        return ( soundex ( word , max_length , 'American' , reverse , zero_pad ) , soundex ( word [ 2 : ] , max_length , 'American' , reverse , zero_pad ) , )
    # Otherwise , proceed as usual ( var = ' American ' mode , ostensibly )
word = '' . join ( c for c in word if c in self . _uc_set )
# Nothing to convert , return base case
if not word :
    if zero_pad :
        return '0' * max_length
    return '0'
# Reverse word if computing Reverse Soundex
if reverse :
    word = word [ : : - 1 ]
# apply the Soundex algorithm
sdx = word . translate ( self . _trans )
if var == 'special' :
    sdx = sdx . replace ( '9' , '0' )
    # special rule for 1880-1910 census
else :
    sdx = sdx . replace ( '9' , '' )
    # rule 1
sdx = self . _delete_consecutive_repeats ( sdx )
# rule 3
if word [ 0 ] in 'HW' :
    sdx = word [ 0 ] + sdx
else :
    sdx = word [ 0 ] + sdx [ 1 : ]
sdx = sdx . replace ( '0' , '' )
# rule 1
if zero_pad :
    sdx += '0' * max_length
# rule 4
return sdx [ : max_length ]


signature:
def fingerprint ( self , phrase , joiner = ' ' ) :
    """Return string fingerprint .
 Parameters
 phrase : str
 The string from which to calculate the fingerprint
 joiner : str
 The string that will be placed between each word
 Returns
 str
 The fingerprint of the phrase
 Example
 > > > sf = String ( )
 > > > sf . fingerprint ( ' The quick brown fox jumped over the lazy dog . ' )
 ' brown dog fox jumped lazy over quick the '"""

implementation:
phrase = unicode_normalize ( 'NFKD' , text_type ( phrase . strip ( ) . lower ( ) ) )
phrase = '' . join ( [ c for c in phrase if c . isalnum ( ) or c . isspace ( ) ] )
phrase = joiner . join ( sorted ( list ( set ( phrase . split ( ) ) ) ) )
return phrase


signature:
def encode ( self , word ) :
    """Return the Russell Index ( integer output ) of a word .
 Parameters
 word : str
 The word to transform
 Returns
 int
 The Russell Index value
 Examples
 > > > pe = RussellIndex ( )
 > > > pe . encode ( ' Christopher ' )
 3813428
 > > > pe . encode ( ' Niall ' )
 715
 > > > pe . encode ( ' Smith ' )
 3614
 > > > pe . encode ( ' Schmidt ' )
 3614"""

implementation:
word = unicode_normalize ( 'NFKD' , text_type ( word . upper ( ) ) )
word = word . replace ( 'ß' , 'SS' )
word = word . replace ( 'GH' , '' )
# discard gh ( rule 3)
word = word . rstrip ( 'SZ' )
# discard / [ sz ] $ / ( rule 3)
# translate according to Russell ' s mapping
word = '' . join ( c for c in word if c in self . _uc_set )
sdx = word . translate ( self . _trans )
# remove any 1s after the first occurrence
one = sdx . find ( '1' ) + 1
if one :
    sdx = sdx [ : one ] + '' . join ( c for c in sdx [ one : ] if c != '1' )
# remove repeating characters
sdx = self . _delete_consecutive_repeats ( sdx )
# return as an int
return int ( sdx ) if sdx else float ( 'NaN' )


signature:
def ipa_to_features ( ipa ) :
    """Convert IPA to features .
 This translates an IPA string of one or more phones to a list of ints
 representing the features of the string .
 Parameters
 ipa : str
 The IPA representation of a phone or series of phones
 Returns
 list of ints
 A representation of the features of the input string
 Examples
 > > > ipa _ to _ features ( ' mut ' )
 [2709662981243185770 , 1825831513894594986 , 2783230754502126250]
 > > > ipa _ to _ features ( ' fon ' )
 [2781702983095331242 , 1825831531074464170 , 2711173160463936106]
 > > > ipa _ to _ features ( ' telz ' )
 [2783230754502126250 , 1826957430176000426 , 2693158761954453926,
 2783230754501863834]"""

implementation:
features = [ ]
pos = 0
ipa = normalize ( 'NFD' , text_type ( ipa . lower ( ) ) )
maxsymlen = max ( len ( _ ) for _ in _PHONETIC_FEATURES )
while pos < len ( ipa ) :
    found_match = False
    for i in range ( maxsymlen , 0 , - 1 ) :
        if ( pos + i - 1 <= len ( ipa ) and ipa [ pos : pos + i ] in _PHONETIC_FEATURES ) :
            features . append ( _PHONETIC_FEATURES [ ipa [ pos : pos + i ] ] )
            pos += i
            found_match = True
    if not found_match :
        features . append ( - 1 )
        pos += 1
return features


signature:
def get_feature ( vector , feature ) :
    """Get a feature vector .
 This returns a list of ints , equal in length to the vector input ,
 representing presence / absence / neutrality with respect to a particular
 phonetic feature .
 Parameters
 vector : list
 A tuple or list of ints representing the phonetic features of a phone
 or series of phones ( such as is returned by the ipa _ to _ features
 function )
 feature : str
 A feature name from the set :
 - ` ` consonantal ` `
 - ` ` sonorant ` `
 - ` ` syllabic ` `
 - ` ` labial ` `
 - ` ` round ` `
 - ` ` coronal ` `
 - ` ` anterior ` `
 - ` ` distributed ` `
 - ` ` dorsal ` `
 - ` ` high ` `
 - ` ` low ` `
 - ` ` back ` `
 - ` ` tense ` `
 - ` ` pharyngeal ` `
 - ` ` ATR ` `
 - ` ` voice ` `
 - ` ` spread _ glottis ` `
 - ` ` constricted _ glottis ` `
 - ` ` continuant ` `
 - ` ` strident ` `
 - ` ` lateral ` `
 - ` ` delayed _ release ` `
 - ` ` nasal ` `
 Returns
 list of ints
 A list indicating presence / absence / neutrality with respect to the
 feature
 Raises
 AttributeError
 feature must be one of . . .
 Examples
 > > > tails = ipa _ to _ features ( ' telz ' )
 > > > get _ feature ( tails , ' consonantal ' )
 [1 , - 1 , 1 , 1]
 > > > get _ feature ( tails , ' sonorant ' )
 [ - 1 , 1 , 1 , - 1]
 > > > get _ feature ( tails , ' nasal ' )
 [ - 1 , - 1 , - 1 , - 1]
 > > > get _ feature ( tails , ' coronal ' )
 [1 , - 1 , 1 , 1]"""

implementation:
# : param bool binary : if False , - 1 , 0 , & 1 represent - , 0 , & +
# if True , only binary oppositions are allowed :
# 0 & 1 represent - & + and 0s are mapped to -
if feature not in _FEATURE_MASK :
    raise AttributeError ( "feature must be one of: '" + "', '" . join ( ( 'consonantal' , 'sonorant' , 'syllabic' , 'labial' , 'round' , 'coronal' , 'anterior' , 'distributed' , 'dorsal' , 'high' , 'low' , 'back' , 'tense' , 'pharyngeal' , 'ATR' , 'voice' , 'spread_glottis' , 'constricted_glottis' , 'continuant' , 'strident' , 'lateral' , 'delayed_release' , 'nasal' , ) ) + "'" )
# each feature mask contains two bits , one each for - and +
mask = _FEATURE_MASK [ feature ]
# the lower bit represents +
pos_mask = mask >> 1
retvec = [ ]
for char in vector :
    if char < 0 :
        retvec . append ( float ( 'NaN' ) )
    else :
        masked = char & mask
        if masked == 0 :
            retvec . append ( 0 )
        elif masked == mask :
            retvec . append ( 2 )
        elif masked & pos_mask :
            retvec . append ( 1 )
        else :
            retvec . append ( - 1 )
return retvec


signature:
def cmp_features ( feat1 , feat2 ) :
    """Compare features .
 This returns a number in the range [ 0 , 1 ] representing a comparison of two
 feature bundles .
 If one of the bundles is negative , - 1 is returned ( for unknown values )
 If the bundles are identical , 1 is returned .
 If they are inverses of one another , 0 is returned .
 Otherwise , a float representing their similarity is returned .
 Parameters
 feat1 : int
 A feature bundle
 feat2 : int
 A feature bundle
 Returns
 float
 A comparison of the feature bundles
 Examples
 > > > cmp _ features ( ipa _ to _ features ( ' l ' ) [ 0 ] , ipa _ to _ features ( ' l ' ) [ 0 ] )
 1.0
 > > > cmp _ features ( ipa _ to _ features ( ' l ' ) [ 0 ] , ipa _ to _ features ( ' n ' ) [ 0 ] )
 0.8709677419354839
 > > > cmp _ features ( ipa _ to _ features ( ' l ' ) [ 0 ] , ipa _ to _ features ( ' z ' ) [ 0 ] )
 0.8709677419354839
 > > > cmp _ features ( ipa _ to _ features ( ' l ' ) [ 0 ] , ipa _ to _ features ( ' i ' ) [ 0 ] )
 0.564516129032258"""

implementation:
if feat1 < 0 or feat2 < 0 :
    return - 1.0
if feat1 == feat2 :
    return 1.0
magnitude = len ( _FEATURE_MASK )
featxor = feat1 ^ feat2
diffbits = 0
# print ( featxor )
while featxor :
    if featxor & 0b1 :
        diffbits += 1
    featxor >>= 1
# print ( diffbits )
return 1 - ( diffbits / ( 2 * magnitude ) )


signature:
def sim ( self , src , tar ) :
    """Return the length similarity of two strings .
 Length similarity is the ratio of the length of the shorter string to
 the longer .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 Returns
 float
 Length similarity
 Examples
 > > > cmp = Length ( )
 > > > cmp . sim ( ' cat ' , ' hat ' )
 1.0
 > > > cmp . sim ( ' Niall ' , ' Neil ' )
 0.8
 > > > cmp . sim ( ' aluminum ' , ' Catalan ' )
 0.875
 > > > cmp . sim ( ' ATCG ' , ' TAGC ' )
 1.0"""

implementation:
if src == tar :
    return 1.0
if not src or not tar :
    return 0.0
return ( len ( src ) / len ( tar ) if len ( src ) < len ( tar ) else len ( tar ) / len ( src ) )


signature:
def hmean ( nums ) :
    r"""Return harmonic mean .
 The harmonic mean is defined as :
 : math : ` \ frac { | nums | } { \ sum \ limits _ { i } \ frac { 1 } { nums _ i } } `
 Following the behavior of Wolfram | Alpha :
 - If one of the values in nums is 0 , return 0.
 - If more than one value in nums is 0 , return NaN .
 Cf . https : / / en . wikipedia . org / wiki / Harmonic _ mean
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The harmonic mean of nums
 Raises
 AttributeError
 hmean requires at least one value
 Examples
 > > > hmean ( [ 1 , 2 , 3 , 4 ] )
 1.92000004
 > > > hmean ( [ 1 , 2 ] )
 1.33333
 > > > hmean ( [ 0 , 5 , 1000 ] )"""

implementation:
if len ( nums ) < 1 :
    raise AttributeError ( 'hmean requires at least one value' )
elif len ( nums ) == 1 :
    return nums [ 0 ]
else :
    for i in range ( 1 , len ( nums ) ) :
        if nums [ 0 ] != nums [ i ] :
            break
    else :
        return nums [ 0 ]
if 0 in nums :
    if nums . count ( 0 ) > 1 :
        return float ( 'nan' )
    return 0
return len ( nums ) / sum ( 1 / i for i in nums )


signature:
def lmean ( nums ) :
    r"""Return logarithmic mean .
 The logarithmic mean of an arbitrarily long series is defined by
 http : / / www . survo . fi / papers / logmean . pdf
 as :
 : math : ` L ( x _ 1 , x _ 2 , . . . , x _ n ) =
 ( n - 1 ) ! \ sum \ limits _ { i = 1 } ^ n \ frac { x _ i }
 { \ prod \ limits _ { \ substack { j = 1 \ \ j \ ne i } } ^ n
 ln \ frac { x _ i } { x _ j } } `
 Cf . https : / / en . wikipedia . org / wiki / Logarithmic _ mean
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The logarithmic mean of nums
 Raises
 AttributeError
 No two values in the nums list may be equal
 Examples
 > > > lmean ( [ 1 , 2 , 3 , 4 ] )
 2.2724242417489258
 > > > lmean ( [ 1 , 2 ] )
 1.4426950408889634"""

implementation:
if len ( nums ) != len ( set ( nums ) ) :
    raise AttributeError ( 'No two values in the nums list may be equal' )
rolling_sum = 0
for i in range ( len ( nums ) ) :
    rolling_prod = 1
    for j in range ( len ( nums ) ) :
        if i != j :
            rolling_prod *= math . log ( nums [ i ] / nums [ j ] )
    rolling_sum += nums [ i ] / rolling_prod
return math . factorial ( len ( nums ) - 1 ) * rolling_sum


signature:
def imean ( nums ) :
    r"""Return identric ( exponential ) mean .
 The identric mean of two numbers x and y is :
 x if x = y
 otherwise : math : ` \ frac { 1 } { e } \ sqrt [ x - y ] { \ frac { x ^ x } { y ^ y } } `
 Cf . https : / / en . wikipedia . org / wiki / Identric _ mean
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The identric mean of nums
 Raises
 AttributeError
 imean supports no more than two values
 Examples
 > > > imean ( [ 1 , 2 ] )
 1.4715177646857693
 > > > imean ( [ 1 , 0 ] )
 nan
 > > > imean ( [ 2 , 4 ] )
 2.9430355293715387"""

implementation:
if len ( nums ) == 1 :
    return nums [ 0 ]
if len ( nums ) > 2 :
    raise AttributeError ( 'imean supports no more than two values' )
if nums [ 0 ] <= 0 or nums [ 1 ] <= 0 :
    return float ( 'NaN' )
elif nums [ 0 ] == nums [ 1 ] :
    return nums [ 0 ]
return ( 1 / math . e ) * ( nums [ 0 ] ** nums [ 0 ] / nums [ 1 ] ** nums [ 1 ] ) ** ( 1 / ( nums [ 0 ] - nums [ 1 ] ) )


signature:
def seiffert_mean ( nums ) :
    r"""Return Seiffert ' s mean .
 Seiffert ' s mean of two numbers x and y is :
 : math : ` \ frac { x - y } { 4 \ cdot arctan \ sqrt { \ frac { x } { y } } - \ pi } `
 It is defined in : cite : ` Seiffert : 1993 ` .
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 Sieffert ' s mean of nums
 Raises
 AttributeError
 seiffert _ mean supports no more than two values
 Examples
 > > > seiffert _ mean ( [ 1 , 2 ] )
 1.4712939827611637
 > > > seiffert _ mean ( [ 1 , 0 ] )
 0.3183098861837907
 > > > seiffert _ mean ( [ 2 , 4 ] )
 2.9425879655223275
 > > > seiffert _ mean ( [ 2 , 1000 ] )
 336.84053300118825"""

implementation:
if len ( nums ) == 1 :
    return nums [ 0 ]
if len ( nums ) > 2 :
    raise AttributeError ( 'seiffert_mean supports no more than two values' )
if nums [ 0 ] + nums [ 1 ] == 0 or nums [ 0 ] - nums [ 1 ] == 0 :
    return float ( 'NaN' )
return ( nums [ 0 ] - nums [ 1 ] ) / ( 2 * math . asin ( ( nums [ 0 ] - nums [ 1 ] ) / ( nums [ 0 ] + nums [ 1 ] ) ) )


signature:
def lehmer_mean ( nums , exp = 2 ) :
    r"""Return Lehmer mean .
 The Lehmer mean is :
 : math : ` \ frac { \ sum \ limits _ i { x _ i ^ p } } { \ sum \ limits _ i { x _ i ^ ( p - 1 ) } } `
 Cf . https : / / en . wikipedia . org / wiki / Lehmer _ mean
 Parameters
 nums : list
 A series of numbers
 exp : numeric
 The exponent of the Lehmer mean
 Returns
 float
 The Lehmer mean of nums for the given exponent
 Examples
 > > > lehmer _ mean ( [ 1 , 2 , 3 , 4 ] )
 3.0
 > > > lehmer _ mean ( [ 1 , 2 ] )
 1.666667
 > > > lehmer _ mean ( [ 0 , 5 , 1000 ] )
 995.0497512437811"""

implementation: return sum ( x ** exp for x in nums ) / sum ( x ** ( exp - 1 ) for x in nums )


signature:
def heronian_mean ( nums ) :
    r"""Return Heronian mean .
 The Heronian mean is :
 : math : ` \ frac { \ sum \ limits _ { i , j } \ sqrt { { x _ i \ cdot x _ j } } }
 { | nums | \ cdot \ frac { | nums | + 1 } { 2 } } `
 for : math : ` j \ ge i `
 Cf . https : / / en . wikipedia . org / wiki / Heronian _ mean
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The Heronian mean of nums
 Examples
 > > > heronian _ mean ( [ 1 , 2 , 3 , 4 ] )
 2.3888282852609093
 > > > heronian _ mean ( [ 1 , 2 ] )
 1.4714045207910316
 > > > heronian _ mean ( [ 0 , 5 , 1000 ] )
 179.28511301977582"""

implementation:
mag = len ( nums )
rolling_sum = 0
for i in range ( mag ) :
    for j in range ( i , mag ) :
        if nums [ i ] == nums [ j ] :
            rolling_sum += nums [ i ]
        else :
            rolling_sum += ( nums [ i ] * nums [ j ] ) ** 0.5
return rolling_sum * 2 / ( mag * ( mag + 1 ) )


signature:
def hoelder_mean ( nums , exp = 2 ) :
    r"""Return Hölder ( power / generalized ) mean .
 The Hölder mean is defined as :
 : math : ` \ sqrt [ p ] { \ frac { 1 } { | nums | } \ cdot \ sum \ limits _ i { x _ i ^ p } } `
 for : math : ` p \ ne 0 ` , and the geometric mean for : math : ` p = 0 `
 Cf . https : / / en . wikipedia . org / wiki / Generalized _ mean
 Parameters
 nums : list
 A series of numbers
 exp : numeric
 The exponent of the Hölder mean
 Returns
 float
 The Hölder mean of nums for the given exponent
 Examples
 > > > hoelder _ mean ( [ 1 , 2 , 3 , 4 ] )
 2.7386127875258306
 > > > hoelder _ mean ( [ 1 , 2 ] )
 1.5811388300841898
 > > > hoelder _ mean ( [ 0 , 5 , 1000 ] )
 577.3574860228857"""

implementation:
if exp == 0 :
    return gmean ( nums )
return ( ( 1 / len ( nums ) ) * sum ( i ** exp for i in nums ) ) ** ( 1 / exp )


signature:
def agmean ( nums ) :
    """Return arithmetic - geometric mean .
 Iterates between arithmetic & geometric means until they converge to
 a single value ( rounded to 12 digits ) .
 Cf . https : / / en . wikipedia . org / wiki / Arithmetic - geometric _ mean
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The arithmetic - geometric mean of nums
 Examples
 > > > agmean ( [ 1 , 2 , 3 , 4 ] )
 2.3545004777751077
 > > > agmean ( [ 1 , 2 ] )
 1.4567910310469068
 > > > agmean ( [ 0 , 5 , 1000 ] )
 2.9753977059954195e - 13"""

implementation:
m_a = amean ( nums )
m_g = gmean ( nums )
if math . isnan ( m_a ) or math . isnan ( m_g ) :
    return float ( 'nan' )
while round ( m_a , 12 ) != round ( m_g , 12 ) :
    m_a , m_g = ( m_a + m_g ) / 2 , ( m_a * m_g ) ** ( 1 / 2 )
return m_a


signature:
def ghmean ( nums ) :
    """Return geometric - harmonic mean .
 Iterates between geometric & harmonic means until they converge to
 a single value ( rounded to 12 digits ) .
 Cf . https : / / en . wikipedia . org / wiki / Geometric - harmonic _ mean
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The geometric - harmonic mean of nums
 Examples
 > > > ghmean ( [ 1 , 2 , 3 , 4 ] )
 2.058868154613003
 > > > ghmean ( [ 1 , 2 ] )
 1.3728805006183502
 > > > ghmean ( [ 0 , 5 , 1000 ] )
 0.0
 > > > ghmean ( [ 0 , 0 ] )
 0.0
 > > > ghmean ( [ 0 , 0 , 5 ] )
 nan"""

implementation:
m_g = gmean ( nums )
m_h = hmean ( nums )
if math . isnan ( m_g ) or math . isnan ( m_h ) :
    return float ( 'nan' )
while round ( m_h , 12 ) != round ( m_g , 12 ) :
    m_g , m_h = ( m_g * m_h ) ** ( 1 / 2 ) , ( 2 * m_g * m_h ) / ( m_g + m_h )
return m_g


signature:
def aghmean ( nums ) :
    """Return arithmetic - geometric - harmonic mean .
 Iterates over arithmetic , geometric , & harmonic means until they
 converge to a single value ( rounded to 12 digits ) , following the
 method described in : cite : ` Raissouli : 2009 ` .
 Parameters
 nums : list
 A series of numbers
 Returns
 float
 The arithmetic - geometric - harmonic mean of nums
 Examples
 > > > aghmean ( [ 1 , 2 , 3 , 4 ] )
 2.198327159900212
 > > > aghmean ( [ 1 , 2 ] )
 1.4142135623731884
 > > > aghmean ( [ 0 , 5 , 1000 ] )
 335.0"""

implementation:
m_a = amean ( nums )
m_g = gmean ( nums )
m_h = hmean ( nums )
if math . isnan ( m_a ) or math . isnan ( m_g ) or math . isnan ( m_h ) :
    return float ( 'nan' )
while round ( m_a , 12 ) != round ( m_g , 12 ) and round ( m_g , 12 ) != round ( m_h , 12 ) :
    m_a , m_g , m_h = ( ( m_a + m_g + m_h ) / 3 , ( m_a * m_g * m_h ) ** ( 1 / 3 ) , 3 / ( 1 / m_a + 1 / m_g + 1 / m_h ) , )
return m_a


signature:
def median ( nums ) :
    """Return median .
 With numbers sorted by value , the median is the middle value ( if there is
 an odd number of values ) or the arithmetic mean of the two middle values
 ( if there is an even number of values ) .
 Cf . https : / / en . wikipedia . org / wiki / Median
 Parameters
 nums : list
 A series of numbers
 Returns
 int or float
 The median of nums
 Examples
 > > > median ( [ 1 , 2 , 3 ] )
 > > > median ( [ 1 , 2 , 3 , 4 ] )
 2.5
 > > > median ( [ 1 , 2 , 2 , 4 ] )"""

implementation:
nums = sorted ( nums )
mag = len ( nums )
if mag % 2 :
    mag = int ( ( mag - 1 ) / 2 )
    return nums [ mag ]
mag = int ( mag / 2 )
med = ( nums [ mag - 1 ] + nums [ mag ] ) / 2
return med if not med . is_integer ( ) else int ( med )


signature:
def var ( nums , mean_func = amean , ddof = 0 ) :
    r"""Calculate the variance .
 The variance ( : math : ` \ sigma ^ 2 ` ) of a series of numbers ( : math : ` x _ i ` ) with
 mean : math : ` \ mu ` and population : math : ` N ` is :
 : math : ` \ sigma ^ 2 = \ frac { 1 } { N } \ sum _ { i = 1 } ^ { N } ( x _ i - \ mu ) ^ 2 ` .
 Cf . https : / / en . wikipedia . org / wiki / Variance
 Parameters
 nums : list
 A series of numbers
 mean _ func : function
 A mean function ( amean by default )
 ddof : int
 The degrees of freedom ( 0 by default )
 Returns
 float
 The variance of the values in the series
 Examples
 > > > var ( [ 1 , 1 , 1 , 1 ] )
 0.0
 > > > var ( [ 1 , 2 , 3 , 4 ] )
 1.25
 > > > round ( var ( [ 1 , 2 , 3 , 4 ] , ddof = 1 ) , 12)
 1.666667"""

implementation:
x_bar = mean_func ( nums )
return sum ( ( x - x_bar ) ** 2 for x in nums ) / ( len ( nums ) - ddof )


signature:
def stem ( self , word ) :
    """Return the stem of a word according to the Schinke stemmer .
 Parameters
 word : str
 The word to stem
 Returns
 str
 Word stem
 Examples
 > > > stmr = Schinke ( )
 > > > stmr . stem ( ' atque ' )
 { ' n ' : ' atque ' , ' v ' : ' atque ' }
 > > > stmr . stem ( ' census ' )
 { ' n ' : ' cens ' , ' v ' : ' censu ' }
 > > > stmr . stem ( ' virum ' )
 { ' n ' : ' uir ' , ' v ' : ' uiru ' }
 > > > stmr . stem ( ' populusque ' )
 { ' n ' : ' popul ' , ' v ' : ' populu ' }
 > > > stmr . stem ( ' senatus ' )
 { ' n ' : ' senat ' , ' v ' : ' senatu ' }"""

implementation:
word = normalize ( 'NFKD' , text_type ( word . lower ( ) ) )
word = '' . join ( c for c in word if c in { 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , } )
# Rule 2
word = word . replace ( 'j' , 'i' ) . replace ( 'v' , 'u' )
# Rule 3
if word [ - 3 : ] == 'que' : # This diverges from the paper by also returning ' que ' itself
# unstemmed
    if word [ : - 3 ] in self . _keep_que or word == 'que' :
        return { 'n' : word , 'v' : word }
    else :
        word = word [ : - 3 ]
# Base case will mean returning the words as is
noun = word
verb = word
# Rule 4
for endlen in range ( 4 , 0 , - 1 ) :
    if word [ - endlen : ] in self . _n_endings [ endlen ] :
        if len ( word ) - 2 >= endlen :
            noun = word [ : - endlen ]
        else :
            noun = word
        break
for endlen in range ( 6 , 0 , - 1 ) :
    if word [ - endlen : ] in self . _v_endings_strip [ endlen ] :
        if len ( word ) - 2 >= endlen :
            verb = word [ : - endlen ]
        else :
            verb = word
        break
    if word [ - endlen : ] in self . _v_endings_alter [ endlen ] :
        if word [ - endlen : ] in { 'iuntur' , 'erunt' , 'untur' , 'iunt' , 'unt' , } :
            new_word = word [ : - endlen ] + 'i'
            addlen = 1
        elif word [ - endlen : ] in { 'beris' , 'bor' , 'bo' } :
            new_word = word [ : - endlen ] + 'bi'
            addlen = 2
        else :
            new_word = word [ : - endlen ] + 'eri'
            addlen = 3
        # Technically this diverges from the paper by considering the
        # length of the stem without the new suffix
        if len ( new_word ) >= 2 + addlen :
            verb = new_word
        else :
            verb = word
        break
return { 'n' : noun , 'v' : verb }


signature:
def onca ( word , max_length = 4 , zero_pad = True ) :
    """Return the Oxford Name Compression Algorithm ( ONCA ) code for a word .
 This is a wrapper for : py : meth : ` ONCA . encode ` .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The maximum length ( default 5 ) of the code to return
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length string
 Returns
 str
 The ONCA code
 Examples
 > > > onca ( ' Christopher ' )
 ' C623'
 > > > onca ( ' Niall ' )
 ' N400'
 > > > onca ( ' Smith ' )
 ' S530'
 > > > onca ( ' Schmidt ' )
 ' S530'"""

implementation: return ONCA ( ) . encode ( word , max_length , zero_pad )


signature:
def encode ( self , word , max_length = 4 , zero_pad = True ) :
    """Return the Oxford Name Compression Algorithm ( ONCA ) code for a word .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The maximum length ( default 5 ) of the code to return
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length
 string
 Returns
 str
 The ONCA code
 Examples
 > > > pe = ONCA ( )
 > > > pe . encode ( ' Christopher ' )
 ' C623'
 > > > pe . encode ( ' Niall ' )
 ' N400'
 > > > pe . encode ( ' Smith ' )
 ' S530'
 > > > pe . encode ( ' Schmidt ' )
 ' S530'"""

implementation:
# In the most extreme case , 3 characters of NYSIIS input can be
# compressed to one character of output , so give it triple the
# max _ length .
return self . _soundex . encode ( self . _nysiis . encode ( word , max_length = max_length * 3 ) , max_length , zero_pad = zero_pad , )


signature:
def phonix ( word , max_length = 4 , zero_pad = True ) :
    """Return the Phonix code for a word .
 This is a wrapper for : py : meth : ` Phonix . encode ` .
 Parameters
 word : str
 The word to transform
 max _ length : int
 The length of the code returned ( defaults to 4)
 zero _ pad : bool
 Pad the end of the return value with 0s to achieve a max _ length string
 Returns
 str
 The Phonix value
 Examples
 > > > phonix ( ' Christopher ' )
 ' K683'
 > > > phonix ( ' Niall ' )
 ' N400'
 > > > phonix ( ' Smith ' )
 ' S530'
 > > > phonix ( ' Schmidt ' )
 ' S530'"""

implementation: return Phonix ( ) . encode ( word , max_length , zero_pad )


signature:
def editex ( src , tar , cost = ( 0 , 1 , 2 ) , local = False ) :
    """Return the Editex distance between two strings .
 This is a wrapper for : py : meth : ` Editex . dist _ abs ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 cost : tuple
 A 3 - tuple representing the cost of the four possible edits : match ,
 same - group , and mismatch respectively ( by default : ( 0 , 1 , 2 ) )
 local : bool
 If True , the local variant of Editex is used
 Returns
 int
 Editex distance
 Examples
 > > > editex ( ' cat ' , ' hat ' )
 > > > editex ( ' Niall ' , ' Neil ' )
 > > > editex ( ' aluminum ' , ' Catalan ' )
 12
 > > > editex ( ' ATCG ' , ' TAGC ' )"""

implementation: return Editex ( ) . dist_abs ( src , tar , cost , local )


signature:
def dist_editex ( src , tar , cost = ( 0 , 1 , 2 ) , local = False ) :
    """Return the normalized Editex distance between two strings .
 This is a wrapper for : py : meth : ` Editex . dist ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 cost : tuple
 A 3 - tuple representing the cost of the four possible edits : match ,
 same - group , and mismatch respectively ( by default : ( 0 , 1 , 2 ) )
 local : bool
 If True , the local variant of Editex is used
 Returns
 int
 Normalized Editex distance
 Examples
 > > > round ( dist _ editex ( ' cat ' , ' hat ' ) , 12)
 0.33333
 > > > round ( dist _ editex ( ' Niall ' , ' Neil ' ) , 12)
 0.2
 > > > dist _ editex ( ' aluminum ' , ' Catalan ' )
 0.75
 > > > dist _ editex ( ' ATCG ' , ' TAGC ' )
 0.75"""

implementation: return Editex ( ) . dist ( src , tar , cost , local )


signature:
def sim_editex ( src , tar , cost = ( 0 , 1 , 2 ) , local = False ) :
    """Return the normalized Editex similarity of two strings .
 This is a wrapper for : py : meth : ` Editex . sim ` .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 cost : tuple
 A 3 - tuple representing the cost of the four possible edits : match ,
 same - group , and mismatch respectively ( by default : ( 0 , 1 , 2 ) )
 local : bool
 If True , the local variant of Editex is used
 Returns
 int
 Normalized Editex similarity
 Examples
 > > > round ( sim _ editex ( ' cat ' , ' hat ' ) , 12)
 0.666667
 > > > round ( sim _ editex ( ' Niall ' , ' Neil ' ) , 12)
 0.8
 > > > sim _ editex ( ' aluminum ' , ' Catalan ' )
 0.25
 > > > sim _ editex ( ' ATCG ' , ' TAGC ' )
 0.25"""

implementation: return Editex ( ) . sim ( src , tar , cost , local )


signature:
def dist ( self , src , tar , cost = ( 0 , 1 , 2 ) , local = False ) :
    """Return the normalized Editex distance between two strings .
 The Editex distance is normalized by dividing the Editex distance
 ( calculated by any of the three supported methods ) by the greater of
 the number of characters in src times the cost of a delete and
 the number of characters in tar times the cost of an insert .
 For the case in which all operations have : math : ` cost = 1 ` , this is
 equivalent to the greater of the length of the two strings src & tar .
 Parameters
 src : str
 Source string for comparison
 tar : str
 Target string for comparison
 cost : tuple
 A 3 - tuple representing the cost of the four possible edits : match ,
 same - group , and mismatch respectively ( by default : ( 0 , 1 , 2 ) )
 local : bool
 If True , the local variant of Editex is used
 Returns
 int
 Normalized Editex distance
 Examples
 > > > cmp = Editex ( )
 > > > round ( cmp . dist ( ' cat ' , ' hat ' ) , 12)
 0.33333
 > > > round ( cmp . dist ( ' Niall ' , ' Neil ' ) , 12)
 0.2
 > > > cmp . dist ( ' aluminum ' , ' Catalan ' )
 0.75
 > > > cmp . dist ( ' ATCG ' , ' TAGC ' )
 0.75"""

implementation:
if src == tar :
    return 0.0
mismatch_cost = cost [ 2 ]
return self . dist_abs ( src , tar , cost , local ) / ( max ( len ( src ) * mismatch_cost , len ( tar ) * mismatch_cost ) )


signature:
def position_fingerprint ( word , n_bits = 16 , most_common = MOST_COMMON_LETTERS_CG , bits_per_letter = 3 ) :
    """Return the position fingerprint .
 This is a wrapper for : py : meth : ` Position . fingerprint ` .
 Parameters
 word : str
 The word to fingerprint
 n _ bits : int
 Number of bits in the fingerprint returned
 most _ common : list
 The most common tokens in the target language , ordered by frequency
 bits _ per _ letter : int
 The bits to assign for letter position
 Returns
 int
 The position fingerprint
 Examples
 > > > bin ( position _ fingerprint ( ' hat ' ) )
 '0b1110100011111'
 > > > bin ( position _ fingerprint ( ' niall ' ) )
 '0b111110101110010'
 > > > bin ( position _ fingerprint ( ' colin ' ) )
 '0b111110010111'
 > > > bin ( position _ fingerprint ( ' atcg ' ) )
 '0b11100100011111'
 > > > bin ( position _ fingerprint ( ' entreatment ' ) )
 '0b101011111'"""

implementation: return Position ( ) . fingerprint ( word , n_bits , most_common , bits_per_letter )


signature:
def fingerprint ( self , word , n_bits = 16 , most_common = MOST_COMMON_LETTERS_CG , bits_per_letter = 3 , ) :
    """Return the position fingerprint .
 Parameters
 word : str
 The word to fingerprint
 n _ bits : int
 Number of bits in the fingerprint returned
 most _ common : list
 The most common tokens in the target language , ordered by frequency
 bits _ per _ letter : int
 The bits to assign for letter position
 Returns
 int
 The position fingerprint
 Examples
 > > > bin ( position _ fingerprint ( ' hat ' ) )
 '0b1110100011111'
 > > > bin ( position _ fingerprint ( ' niall ' ) )
 '0b111110101110010'
 > > > bin ( position _ fingerprint ( ' colin ' ) )
 '0b111110010111'
 > > > bin ( position _ fingerprint ( ' atcg ' ) )
 '0b11100100011111'
 > > > bin ( position _ fingerprint ( ' entreatment ' ) )
 '0b101011111'"""

implementation:
position = { }
for pos , letter in enumerate ( word ) :
    if letter not in position and letter in most_common :
        position [ letter ] = min ( pos , 2 ** bits_per_letter - 1 )
fingerprint = 0
for letter in most_common :
    if n_bits :
        fingerprint <<= min ( bits_per_letter , n_bits )
        if letter in position :
            fingerprint += min ( position [ letter ] , 2 ** n_bits - 1 )
        else :
            fingerprint += min ( 2 ** bits_per_letter - 1 , 2 ** n_bits - 1 )
        n_bits -= min ( bits_per_letter , n_bits )
    else :
        break
for _ in range ( n_bits ) :
    fingerprint <<= 1
    fingerprint += 1
return fingerprint


signature:
def stem ( self , word ) :
    """Return Caumanns German stem .
 Parameters
 word : str
 The word to stem
 Returns
 str
 Word stem
 Examples
 > > > stmr = Caumanns ( )
 > > > stmr . stem ( ' lesen ' )
 ' les '
 > > > stmr . stem ( ' graues ' )
 ' grau '
 > > > stmr . stem ( ' buchstabieren ' )
 ' buchstabier '"""

implementation:
if not word :
    return ''
upper_initial = word [ 0 ] . isupper ( )
word = normalize ( 'NFC' , text_type ( word . lower ( ) ) )
# # Part 2 : Substitution
# 1 . Change umlauts to corresponding vowels & ß to ss
word = word . translate ( self . _umlauts )
word = word . replace ( 'ß' , 'ss' )
# 2 . Change second of doubled characters to *
new_word = word [ 0 ]
for i in range ( 1 , len ( word ) ) :
    if new_word [ i - 1 ] == word [ i ] :
        new_word += '*'
    else :
        new_word += word [ i ]
word = new_word
# 3 . Replace sch , ch , ei , ie with $ , § , % , &
word = word . replace ( 'sch' , '$' )
word = word . replace ( 'ch' , '§' )
word = word . replace ( 'ei' , '%' )
word = word . replace ( 'ie' , '&' )
word = word . replace ( 'ig' , '#' )
word = word . replace ( 'st' , '!' )
# # Part 1 : Recursive Context - Free Stripping
# 1 . Remove the following 7 suffixes recursively
while len ( word ) > 3 :
    if ( len ( word ) > 4 and word [ - 2 : ] in { 'em' , 'er' } ) or ( len ( word ) > 5 and word [ - 2 : ] == 'nd' ) :
        word = word [ : - 2 ]
    elif ( word [ - 1 ] in { 'e' , 's' , 'n' } ) or ( not upper_initial and word [ - 1 ] in { 't' , '!' } ) :
        word = word [ : - 1 ]
    else :
        break
# Additional optimizations :
if len ( word ) > 5 and word [ - 5 : ] == 'erin*' :
    word = word [ : - 1 ]
if word [ - 1 ] == 'z' :
    word = word [ : - 1 ] + 'x'
# Reverse substitutions :
word = word . replace ( '$' , 'sch' )
word = word . replace ( '§' , 'ch' )
word = word . replace ( '%' , 'ei' )
word = word . replace ( '&' , 'ie' )
word = word . replace ( '#' , 'ig' )
word = word . replace ( '!' , 'st' )
# Expand doubled
word = '' . join ( [ word [ 0 ] ] + [ word [ i - 1 ] if word [ i ] == '*' else word [ i ] for i in range ( 1 , len ( word ) ) ] )
# Finally , convert gege to ge
if len ( word ) > 4 :
    word = word . replace ( 'gege' , 'ge' , 1 )
return word