return NCDbz2().dist(src, tar)<EOL>

Return the NCD between two strings using bzip2 compression.

    This is a wrapper for :py:meth:`NCDbz2.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison

    Returns
    -------
    float
        Compression distance

    Examples
    --------
    >>> dist_ncd_bz2('cat', 'hat')
    0.06666666666666667
    >>> dist_ncd_bz2('Niall', 'Neil')
    0.03125
    >>> dist_ncd_bz2('aluminum', 'Catalan')
    0.17647058823529413
    >>> dist_ncd_bz2('ATCG', 'TAGC')
    0.03125


return NCDbz2().sim(src, tar)<EOL>

Return the NCD similarity between two strings using bzip2 compression.

    This is a wrapper for :py:meth:`NCDbz2.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison

    Returns
    -------
    float
        Compression similarity

    Examples
    --------
    >>> sim_ncd_bz2('cat', 'hat')
    0.9333333333333333
    >>> sim_ncd_bz2('Niall', 'Neil')
    0.96875
    >>> sim_ncd_bz2('aluminum', 'Catalan')
    0.8235294117647058
    >>> sim_ncd_bz2('ATCG', 'TAGC')
    0.96875


self._level = level<EOL>

Initialize bzip2 compressor.

        Parameters
        ----------
        level : int
            The compression level (0 to 9)


if src == tar:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>src = src.encode('<STR_LIT:utf-8>')<EOL>tar = tar.encode('<STR_LIT:utf-8>')<EOL>src_comp = bz2.compress(src, self._level)[<NUM_LIT:10>:]<EOL>tar_comp = bz2.compress(tar, self._level)[<NUM_LIT:10>:]<EOL>concat_comp = bz2.compress(src + tar, self._level)[<NUM_LIT:10>:]<EOL>concat_comp2 = bz2.compress(tar + src, self._level)[<NUM_LIT:10>:]<EOL>return (<EOL>min(len(concat_comp), len(concat_comp2))<EOL>- min(len(src_comp), len(tar_comp))<EOL>) / max(len(src_comp), len(tar_comp))<EOL>

Return the NCD between two strings using bzip2 compression.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Compression distance

        Examples
        --------
        >>> cmp = NCDbz2()
        >>> cmp.dist('cat', 'hat')
        0.06666666666666667
        >>> cmp.dist('Niall', 'Neil')
        0.03125
        >>> cmp.dist('aluminum', 'Catalan')
        0.17647058823529413
        >>> cmp.dist('ATCG', 'TAGC')
        0.03125


return JaroWinkler().sim(<EOL>src, tar, qval, mode, long_strings, boost_threshold, scaling_factor<EOL>)<EOL>

Return the Jaro or Jaro-Winkler similarity of two strings.

    This is a wrapper for :py:meth:`JaroWinkler.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    qval : int
        The length of each q-gram (defaults to 1: character-wise matching)
    mode : str
        Indicates which variant of this distance metric to compute:

            - ``winkler`` -- computes the Jaro-Winkler distance (default) which
              increases the score for matches near the start of the word
            - ``jaro`` -- computes the Jaro distance

    long_strings : bool
        Set to True to "Increase the probability of a match when the number of
        matched characters is large. This option allows for a little more
        tolerance when the strings are large. It is not an appropriate test
        when comparing fixedlength fields such as phone and social security
        numbers." (Used in 'winkler' mode only.)
    boost_threshold : float
        A value between 0 and 1, below which the Winkler boost is not applied
        (defaults to 0.7). (Used in 'winkler' mode only.)
    scaling_factor : float
        A value between 0 and 0.25, indicating by how much to boost scores for
        matching prefixes (defaults to 0.1). (Used in 'winkler' mode only.)

    Returns
    -------
    float
        Jaro or Jaro-Winkler similarity

    Examples
    --------
    >>> round(sim_jaro_winkler('cat', 'hat'), 12)
    0.777777777778
    >>> round(sim_jaro_winkler('Niall', 'Neil'), 12)
    0.805
    >>> round(sim_jaro_winkler('aluminum', 'Catalan'), 12)
    0.60119047619
    >>> round(sim_jaro_winkler('ATCG', 'TAGC'), 12)
    0.833333333333

    >>> round(sim_jaro_winkler('cat', 'hat', mode='jaro'), 12)
    0.777777777778
    >>> round(sim_jaro_winkler('Niall', 'Neil', mode='jaro'), 12)
    0.783333333333
    >>> round(sim_jaro_winkler('aluminum', 'Catalan', mode='jaro'), 12)
    0.60119047619
    >>> round(sim_jaro_winkler('ATCG', 'TAGC', mode='jaro'), 12)
    0.833333333333


return JaroWinkler().dist(<EOL>src, tar, qval, mode, long_strings, boost_threshold, scaling_factor<EOL>)<EOL>

Return the Jaro or Jaro-Winkler distance between two strings.

    This is a wrapper for :py:meth:`JaroWinkler.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    qval : int
        The length of each q-gram (defaults to 1: character-wise matching)
    mode : str
        Indicates which variant of this distance metric to compute:

            - ``winkler`` -- computes the Jaro-Winkler distance (default) which
              increases the score for matches near the start of the word
            - ``jaro`` -- computes the Jaro distance

    long_strings : bool
        Set to True to "Increase the probability of a match when the number of
        matched characters is large. This option allows for a little more
        tolerance when the strings are large. It is not an appropriate test
        when comparing fixedlength fields such as phone and social security
        numbers." (Used in 'winkler' mode only.)
    boost_threshold : float
        A value between 0 and 1, below which the Winkler boost is not applied
        (defaults to 0.7). (Used in 'winkler' mode only.)
    scaling_factor : float
        A value between 0 and 0.25, indicating by how much to boost scores for
        matching prefixes (defaults to 0.1). (Used in 'winkler' mode only.)

    Returns
    -------
    float
        Jaro or Jaro-Winkler distance

    Examples
    --------
    >>> round(dist_jaro_winkler('cat', 'hat'), 12)
    0.222222222222
    >>> round(dist_jaro_winkler('Niall', 'Neil'), 12)
    0.195
    >>> round(dist_jaro_winkler('aluminum', 'Catalan'), 12)
    0.39880952381
    >>> round(dist_jaro_winkler('ATCG', 'TAGC'), 12)
    0.166666666667

    >>> round(dist_jaro_winkler('cat', 'hat', mode='jaro'), 12)
    0.222222222222
    >>> round(dist_jaro_winkler('Niall', 'Neil', mode='jaro'), 12)
    0.216666666667
    >>> round(dist_jaro_winkler('aluminum', 'Catalan', mode='jaro'), 12)
    0.39880952381
    >>> round(dist_jaro_winkler('ATCG', 'TAGC', mode='jaro'), 12)
    0.166666666667


if mode == '<STR_LIT>':<EOL><INDENT>if boost_threshold > <NUM_LIT:1> or boost_threshold < <NUM_LIT:0>:<EOL><INDENT>raise ValueError(<EOL>'<STR_LIT>'<EOL>+ '<STR_LIT>'<EOL>)<EOL><DEDENT>if scaling_factor > <NUM_LIT> or scaling_factor < <NUM_LIT:0>:<EOL><INDENT>raise ValueError(<EOL>'<STR_LIT>'<EOL>+ '<STR_LIT>'<EOL>)<EOL><DEDENT><DEDENT>if src == tar:<EOL><INDENT>return <NUM_LIT:1.0><EOL><DEDENT>src = QGrams(src.strip(), qval)._ordered_list<EOL>tar = QGrams(tar.strip(), qval)._ordered_list<EOL>lens = len(src)<EOL>lent = len(tar)<EOL>if lens == <NUM_LIT:0> or lent == <NUM_LIT:0>:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>if lens > lent:<EOL><INDENT>search_range = lens<EOL>minv = lent<EOL><DEDENT>else:<EOL><INDENT>search_range = lent<EOL>minv = lens<EOL><DEDENT>src_flag = [<NUM_LIT:0>] * search_range<EOL>tar_flag = [<NUM_LIT:0>] * search_range<EOL>search_range = max(<NUM_LIT:0>, search_range // <NUM_LIT:2> - <NUM_LIT:1>)<EOL>num_com = <NUM_LIT:0><EOL>yl1 = lent - <NUM_LIT:1><EOL>for i in range(lens):<EOL><INDENT>low_lim = (i - search_range) if (i >= search_range) else <NUM_LIT:0><EOL>hi_lim = (i + search_range) if ((i + search_range) <= yl1) else yl1<EOL>for j in range(low_lim, hi_lim + <NUM_LIT:1>):<EOL><INDENT>if (tar_flag[j] == <NUM_LIT:0>) and (tar[j] == src[i]):<EOL><INDENT>tar_flag[j] = <NUM_LIT:1><EOL>src_flag[i] = <NUM_LIT:1><EOL>num_com += <NUM_LIT:1><EOL>break<EOL><DEDENT><DEDENT><DEDENT>if num_com == <NUM_LIT:0>:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>k = n_trans = <NUM_LIT:0><EOL>for i in range(lens):<EOL><INDENT>if src_flag[i] != <NUM_LIT:0>:<EOL><INDENT>j = <NUM_LIT:0><EOL>for j in range(k, lent):  <EOL><INDENT>if tar_flag[j] != <NUM_LIT:0>:<EOL><INDENT>k = j + <NUM_LIT:1><EOL>break<EOL><DEDENT><DEDENT>if src[i] != tar[j]:<EOL><INDENT>n_trans += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>n_trans //= <NUM_LIT:2><EOL>weight = (<EOL>num_com / lens + num_com / lent + (num_com - n_trans) / num_com<EOL>)<EOL>weight /= <NUM_LIT><EOL>if mode == '<STR_LIT>' and weight > boost_threshold:<EOL><INDENT>j = <NUM_LIT:4> if (minv >= <NUM_LIT:4>) else minv<EOL>i = <NUM_LIT:0><EOL>while (i < j) and (src[i] == tar[i]):<EOL><INDENT>i += <NUM_LIT:1><EOL><DEDENT>weight += i * scaling_factor * (<NUM_LIT:1.0> - weight)<EOL>if (<EOL>long_strings<EOL>and (minv > <NUM_LIT:4>)<EOL>and (num_com > i + <NUM_LIT:1>)<EOL>and (<NUM_LIT:2> * num_com >= minv + i)<EOL>):<EOL><INDENT>weight += (<NUM_LIT:1.0> - weight) * (<EOL>(num_com - i - <NUM_LIT:1>) / (lens + lent - i * <NUM_LIT:2> + <NUM_LIT:2>)<EOL>)<EOL><DEDENT><DEDENT>return weight<EOL>

Return the Jaro or Jaro-Winkler similarity of two strings.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        qval : int
            The length of each q-gram (defaults to 1: character-wise matching)
        mode : str
            Indicates which variant of this distance metric to compute:

                - ``winkler`` -- computes the Jaro-Winkler distance (default)
                  which increases the score for matches near the start of the
                  word
                - ``jaro`` -- computes the Jaro distance

        long_strings : bool
            Set to True to "Increase the probability of a match when the number
            of matched characters is large. This option allows for a little
            more tolerance when the strings are large. It is not an appropriate
            test when comparing fixed length fields such as phone and social
            security numbers." (Used in 'winkler' mode only.)
        boost_threshold : float
            A value between 0 and 1, below which the Winkler boost is not
            applied (defaults to 0.7). (Used in 'winkler' mode only.)
        scaling_factor : float
            A value between 0 and 0.25, indicating by how much to boost scores
            for matching prefixes (defaults to 0.1). (Used in 'winkler' mode
            only.)

        Returns
        -------
        float
            Jaro or Jaro-Winkler similarity

        Raises
        ------
        ValueError
            Unsupported boost_threshold assignment; boost_threshold must be
            between 0 and 1.
        ValueError
            Unsupported scaling_factor assignment; scaling_factor must be
            between 0 and 0.25.'

        Examples
        --------
        >>> round(sim_jaro_winkler('cat', 'hat'), 12)
        0.777777777778
        >>> round(sim_jaro_winkler('Niall', 'Neil'), 12)
        0.805
        >>> round(sim_jaro_winkler('aluminum', 'Catalan'), 12)
        0.60119047619
        >>> round(sim_jaro_winkler('ATCG', 'TAGC'), 12)
        0.833333333333

        >>> round(sim_jaro_winkler('cat', 'hat', mode='jaro'), 12)
        0.777777777778
        >>> round(sim_jaro_winkler('Niall', 'Neil', mode='jaro'), 12)
        0.783333333333
        >>> round(sim_jaro_winkler('aluminum', 'Catalan', mode='jaro'), 12)
        0.60119047619
        >>> round(sim_jaro_winkler('ATCG', 'TAGC', mode='jaro'), 12)
        0.833333333333


def sim_overlap(src, tar, qval=<NUM_LIT:2>):

return Overlap().sim(src, tar, qval)<EOL>

r"""Return the overlap coefficient of two strings.

    This is a wrapper for :py:meth:`Overlap.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

    Returns
    -------
    float
        Overlap similarity

    Examples
    --------
    >>> sim_overlap('cat', 'hat')
    0.5
    >>> sim_overlap('Niall', 'Neil')
    0.4
    >>> sim_overlap('aluminum', 'Catalan')
    0.125
    >>> sim_overlap('ATCG', 'TAGC')
    0.0


def dist_overlap(src, tar, qval=<NUM_LIT:2>):

return Overlap().dist(src, tar, qval)<EOL>

Return the overlap distance between two strings.

    This is a wrapper for :py:meth:`Overlap.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

    Returns
    -------
    float
        Overlap distance

    Examples
    --------
    >>> dist_overlap('cat', 'hat')
    0.5
    >>> dist_overlap('Niall', 'Neil')
    0.6
    >>> dist_overlap('aluminum', 'Catalan')
    0.875
    >>> dist_overlap('ATCG', 'TAGC')
    1.0


def sim(self, src, tar, qval=<NUM_LIT:2>):

if src == tar:<EOL><INDENT>return <NUM_LIT:1.0><EOL><DEDENT>elif not src or not tar:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>q_src, q_tar = self._get_qgrams(src, tar, qval)<EOL>q_src_mag = sum(q_src.values())<EOL>q_tar_mag = sum(q_tar.values())<EOL>q_intersection_mag = sum((q_src & q_tar).values())<EOL>return q_intersection_mag / min(q_src_mag, q_tar_mag)<EOL>

r"""Return the overlap coefficient 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
            Overlap similarity

        Examples
        --------
        >>> cmp = Overlap()
        >>> cmp.sim('cat', 'hat')
        0.5
        >>> cmp.sim('Niall', 'Neil')
        0.4
        >>> cmp.sim('aluminum', 'Catalan')
        0.125
        >>> cmp.sim('ATCG', 'TAGC')
        0.0


def typo(src, tar, metric='<STR_LIT>', cost=(<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:0.5>, <NUM_LIT:0.5>), layout='<STR_LIT>'):

return Typo().dist_abs(src, tar, metric, cost, layout)<EOL>

Return the typo distance between two strings.

    This is a wrapper for :py:meth:`Typo.typo`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    metric : str
        Supported values include: ``euclidean``, ``manhattan``,
        ``log-euclidean``, and ``log-manhattan``
    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and shift, respectively (by default:
        (1, 1, 0.5, 0.5)) The substitution & shift costs should be
        significantly less than the cost of an insertion & deletion unless a
        log metric is used.
    layout : str
        Name of the keyboard layout to use (Currently supported:
        ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

    Returns
    -------
    float
        Typo distance

    Examples
    --------
    >>> typo('cat', 'hat')
    1.5811388
    >>> typo('Niall', 'Neil')
    2.8251407
    >>> typo('Colin', 'Cuilen')
    3.4142137
    >>> typo('ATCG', 'TAGC')
    2.5

    >>> typo('cat', 'hat', metric='manhattan')
    2.0
    >>> typo('Niall', 'Neil', metric='manhattan')
    3.0
    >>> typo('Colin', 'Cuilen', metric='manhattan')
    3.5
    >>> typo('ATCG', 'TAGC', metric='manhattan')
    2.5

    >>> typo('cat', 'hat', metric='log-manhattan')
    0.804719
    >>> typo('Niall', 'Neil', metric='log-manhattan')
    2.2424533
    >>> typo('Colin', 'Cuilen', metric='log-manhattan')
    2.2424533
    >>> typo('ATCG', 'TAGC', metric='log-manhattan')
    2.3465736


def dist_typo(<EOL>src, tar, metric='<STR_LIT>', cost=(<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:0.5>, <NUM_LIT:0.5>), layout='<STR_LIT>'<EOL>):

return Typo().dist(src, tar, metric, cost, layout)<EOL>

Return the normalized typo distance between two strings.

    This is a wrapper for :py:meth:`Typo.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    metric : str
        Supported values include: ``euclidean``, ``manhattan``,
        ``log-euclidean``, and ``log-manhattan``
    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and shift, respectively (by default:
        (1, 1, 0.5, 0.5)) The substitution & shift costs should be
        significantly less than the cost of an insertion & deletion unless a
        log metric is used.
    layout : str
        Name of the keyboard layout to use (Currently supported:
        ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

    Returns
    -------
    float
        Normalized typo distance

    Examples
    --------
    >>> round(dist_typo('cat', 'hat'), 12)
    0.527046283086
    >>> round(dist_typo('Niall', 'Neil'), 12)
    0.565028142929
    >>> round(dist_typo('Colin', 'Cuilen'), 12)
    0.569035609563
    >>> dist_typo('ATCG', 'TAGC')
    0.625


def sim_typo(<EOL>src, tar, metric='<STR_LIT>', cost=(<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:0.5>, <NUM_LIT:0.5>), layout='<STR_LIT>'<EOL>):

return Typo().sim(src, tar, metric, cost, layout)<EOL>

Return the normalized typo similarity between two strings.

    This is a wrapper for :py:meth:`Typo.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    metric : str
        Supported values include: ``euclidean``, ``manhattan``,
        ``log-euclidean``, and ``log-manhattan``
    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and shift, respectively (by default:
        (1, 1, 0.5, 0.5)) The substitution & shift costs should be
        significantly less than the cost of an insertion & deletion unless a
        log metric is used.
    layout : str
        Name of the keyboard layout to use (Currently supported:
        ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

    Returns
    -------
    float
        Normalized typo similarity

    Examples
    --------
    >>> round(sim_typo('cat', 'hat'), 12)
    0.472953716914
    >>> round(sim_typo('Niall', 'Neil'), 12)
    0.434971857071
    >>> round(sim_typo('Colin', 'Cuilen'), 12)
    0.430964390437
    >>> sim_typo('ATCG', 'TAGC')
    0.375


ins_cost, del_cost, sub_cost, shift_cost = cost<EOL>if src == tar:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>if not src:<EOL><INDENT>return len(tar) * ins_cost<EOL><DEDENT>if not tar:<EOL><INDENT>return len(src) * del_cost<EOL><DEDENT>keyboard = self._keyboard[layout]<EOL>lowercase = {item for sublist in keyboard[<NUM_LIT:0>] for item in sublist}<EOL>uppercase = {item for sublist in keyboard[<NUM_LIT:1>] for item in sublist}<EOL>def _kb_array_for_char(char):<EOL><INDENT>"""<STR_LIT>"""<EOL>if char in lowercase:<EOL><INDENT>return keyboard[<NUM_LIT:0>]<EOL><DEDENT>elif char in uppercase:<EOL><INDENT>return keyboard[<NUM_LIT:1>]<EOL><DEDENT>raise ValueError(char + '<STR_LIT>')<EOL><DEDENT>def _substitution_cost(char1, char2):<EOL><INDENT>cost = sub_cost<EOL>cost *= metric_dict[metric](char1, char2) + shift_cost * (<EOL>_kb_array_for_char(char1) != _kb_array_for_char(char2)<EOL>)<EOL>return cost<EOL><DEDENT>def _get_char_coord(char, kb_array):<EOL><INDENT>"""<STR_LIT>"""<EOL>for row in kb_array:  <EOL><INDENT>if char in row:<EOL><INDENT>return kb_array.index(row), row.index(char)<EOL><DEDENT><DEDENT><DEDENT>def _euclidean_keyboard_distance(char1, char2):<EOL><INDENT>row1, col1 = _get_char_coord(char1, _kb_array_for_char(char1))<EOL>row2, col2 = _get_char_coord(char2, _kb_array_for_char(char2))<EOL>return ((row1 - row2) ** <NUM_LIT:2> + (col1 - col2) ** <NUM_LIT:2>) ** <NUM_LIT:0.5><EOL><DEDENT>def _manhattan_keyboard_distance(char1, char2):<EOL><INDENT>row1, col1 = _get_char_coord(char1, _kb_array_for_char(char1))<EOL>row2, col2 = _get_char_coord(char2, _kb_array_for_char(char2))<EOL>return abs(row1 - row2) + abs(col1 - col2)<EOL><DEDENT>def _log_euclidean_keyboard_distance(char1, char2):<EOL><INDENT>return log(<NUM_LIT:1> + _euclidean_keyboard_distance(char1, char2))<EOL><DEDENT>def _log_manhattan_keyboard_distance(char1, char2):<EOL><INDENT>return log(<NUM_LIT:1> + _manhattan_keyboard_distance(char1, char2))<EOL><DEDENT>metric_dict = {<EOL>'<STR_LIT>': _euclidean_keyboard_distance,<EOL>'<STR_LIT>': _manhattan_keyboard_distance,<EOL>'<STR_LIT>': _log_euclidean_keyboard_distance,<EOL>'<STR_LIT>': _log_manhattan_keyboard_distance,<EOL>}<EOL>d_mat = np_zeros((len(src) + <NUM_LIT:1>, len(tar) + <NUM_LIT:1>), dtype=np_float32)<EOL>for i in range(len(src) + <NUM_LIT:1>):<EOL><INDENT>d_mat[i, <NUM_LIT:0>] = i * del_cost<EOL><DEDENT>for j in range(len(tar) + <NUM_LIT:1>):<EOL><INDENT>d_mat[<NUM_LIT:0>, j] = j * ins_cost<EOL><DEDENT>for i in range(len(src)):<EOL><INDENT>for j in range(len(tar)):<EOL><INDENT>d_mat[i + <NUM_LIT:1>, j + <NUM_LIT:1>] = min(<EOL>d_mat[i + <NUM_LIT:1>, j] + ins_cost,  <EOL>d_mat[i, j + <NUM_LIT:1>] + del_cost,  <EOL>d_mat[i, j]<EOL>+ (<EOL>_substitution_cost(src[i], tar[j])<EOL>if src[i] != tar[j]<EOL>else <NUM_LIT:0><EOL>),  <EOL>)<EOL><DEDENT><DEDENT>return d_mat[len(src), len(tar)]<EOL>

Return the typo distance between two strings.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        metric : str
            Supported values include: ``euclidean``, ``manhattan``,
            ``log-euclidean``, and ``log-manhattan``
        cost : tuple
            A 4-tuple representing the cost of the four possible edits:
            inserts, deletes, substitutions, and shift, respectively (by
            default: (1, 1, 0.5, 0.5)) The substitution & shift costs should be
            significantly less than the cost of an insertion & deletion unless
            a log metric is used.
        layout : str
            Name of the keyboard layout to use (Currently supported:
            ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

        Returns
        -------
        float
            Typo distance

        Raises
        ------
        ValueError
            char not found in any keyboard layouts

        Examples
        --------
        >>> cmp = Typo()
        >>> cmp.dist_abs('cat', 'hat')
        1.5811388
        >>> cmp.dist_abs('Niall', 'Neil')
        2.8251407
        >>> cmp.dist_abs('Colin', 'Cuilen')
        3.4142137
        >>> cmp.dist_abs('ATCG', 'TAGC')
        2.5

        >>> cmp.dist_abs('cat', 'hat', metric='manhattan')
        2.0
        >>> cmp.dist_abs('Niall', 'Neil', metric='manhattan')
        3.0
        >>> cmp.dist_abs('Colin', 'Cuilen', metric='manhattan')
        3.5
        >>> cmp.dist_abs('ATCG', 'TAGC', metric='manhattan')
        2.5

        >>> cmp.dist_abs('cat', 'hat', metric='log-manhattan')
        0.804719
        >>> cmp.dist_abs('Niall', 'Neil', metric='log-manhattan')
        2.2424533
        >>> cmp.dist_abs('Colin', 'Cuilen', metric='log-manhattan')
        2.2424533
        >>> cmp.dist_abs('ATCG', 'TAGC', metric='log-manhattan')
        2.3465736


def dist(<EOL>self,<EOL>src,<EOL>tar,<EOL>metric='<STR_LIT>',<EOL>cost=(<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:0.5>, <NUM_LIT:0.5>),<EOL>layout='<STR_LIT>',<EOL>):

if src == tar:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>ins_cost, del_cost = cost[:<NUM_LIT:2>]<EOL>return self.dist_abs(src, tar, metric, cost, layout) / (<EOL>max(len(src) * del_cost, len(tar) * ins_cost)<EOL>)<EOL>

Return the normalized typo distance between two strings.

        This is typo distance, normalized to [0, 1].

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        metric : str
            Supported values include: ``euclidean``, ``manhattan``,
            ``log-euclidean``, and ``log-manhattan``
        cost : tuple
            A 4-tuple representing the cost of the four possible edits:
            inserts, deletes, substitutions, and shift, respectively (by
            default: (1, 1, 0.5, 0.5)) The substitution & shift costs should be
            significantly less than the cost of an insertion & deletion unless
            a log metric is used.
        layout : str
            Name of the keyboard layout to use (Currently supported:
            ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

        Returns
        -------
        float
            Normalized typo distance

        Examples
        --------
        >>> cmp = Typo()
        >>> round(cmp.dist('cat', 'hat'), 12)
        0.527046283086
        >>> round(cmp.dist('Niall', 'Neil'), 12)
        0.565028142929
        >>> round(cmp.dist('Colin', 'Cuilen'), 12)
        0.569035609563
        >>> cmp.dist('ATCG', 'TAGC')
        0.625


def _get_qgrams(self, src, tar, qval=<NUM_LIT:0>, skip=<NUM_LIT:0>):

if isinstance(src, Counter) and isinstance(tar, Counter):<EOL><INDENT>return src, tar<EOL><DEDENT>if qval > <NUM_LIT:0>:<EOL><INDENT>return QGrams(src, qval, '<STR_LIT>', skip), QGrams(tar, qval, '<STR_LIT>', skip)<EOL><DEDENT>return Counter(src.strip().split()), Counter(tar.strip().split())<EOL>

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}))


def minkowski(src, tar, qval=<NUM_LIT:2>, pval=<NUM_LIT:1>, normalized=False, alphabet=None):

return Minkowski().dist_abs(src, tar, qval, pval, normalized, alphabet)<EOL>

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


def dist_minkowski(src, tar, qval=<NUM_LIT:2>, pval=<NUM_LIT:1>, alphabet=None):

return Minkowski().dist(src, tar, qval, pval, alphabet)<EOL>

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


def sim_minkowski(src, tar, qval=<NUM_LIT:2>, pval=<NUM_LIT:1>, alphabet=None):

return Minkowski().sim(src, tar, qval, pval, alphabet)<EOL>

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


def dist_abs(<EOL>self, src, tar, qval=<NUM_LIT:2>, pval=<NUM_LIT:1>, normalized=False, alphabet=None<EOL>):

q_src, q_tar = self._get_qgrams(src, tar, qval)<EOL>diffs = ((q_src - q_tar) + (q_tar - q_src)).values()<EOL>normalizer = <NUM_LIT:1><EOL>if normalized:<EOL><INDENT>totals = (q_src + q_tar).values()<EOL>if alphabet is not None:<EOL><INDENT>normalizer = (<EOL>alphabet if isinstance(alphabet, Number) else len(alphabet)<EOL>)<EOL><DEDENT>elif pval == <NUM_LIT:0>:<EOL><INDENT>normalizer = len(totals)<EOL><DEDENT>else:<EOL><INDENT>normalizer = sum(_ ** pval for _ in totals) ** (<NUM_LIT:1> / pval)<EOL><DEDENT><DEDENT>if len(diffs) == <NUM_LIT:0>:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>if pval == float('<STR_LIT>'):<EOL><INDENT>return max(diffs) / normalizer<EOL><DEDENT>if pval == <NUM_LIT:0>:<EOL><INDENT>return len(diffs) / normalizer<EOL><DEDENT>return sum(_ ** pval for _ in diffs) ** (<NUM_LIT:1> / pval) / normalizer<EOL>

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


def dist(self, src, tar, qval=<NUM_LIT:2>, pval=<NUM_LIT:1>, alphabet=None):

return self.dist_abs(src, tar, qval, pval, True, alphabet)<EOL>

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


return Suffix().sim(src, tar)<EOL>

Return the suffix similarity of two strings.

    This is a wrapper for :py:meth:`Suffix.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison

    Returns
    -------
    float
        Suffix similarity

    Examples
    --------
    >>> sim_suffix('cat', 'hat')
    0.6666666666666666
    >>> sim_suffix('Niall', 'Neil')
    0.25
    >>> sim_suffix('aluminum', 'Catalan')
    0.0
    >>> sim_suffix('ATCG', 'TAGC')
    0.0


return Suffix().dist(src, tar)<EOL>

Return the suffix distance between two strings.

    This is a wrapper for :py:meth:`Suffix.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison

    Returns
    -------
    float
        Suffix distance

    Examples
    --------
    >>> dist_suffix('cat', 'hat')
    0.33333333333333337
    >>> dist_suffix('Niall', 'Neil')
    0.75
    >>> dist_suffix('aluminum', 'Catalan')
    1.0
    >>> dist_suffix('ATCG', 'TAGC')
    1.0


if src == tar:<EOL><INDENT>return <NUM_LIT:1.0><EOL><DEDENT>if not src or not tar:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>min_word, max_word = (src, tar) if len(src) < len(tar) else (tar, src)<EOL>min_len = len(min_word)<EOL>for i in range(min_len, <NUM_LIT:0>, -<NUM_LIT:1>):<EOL><INDENT>if min_word[-i:] == max_word[-i:]:<EOL><INDENT>return i / min_len<EOL><DEDENT><DEDENT>return <NUM_LIT:0.0><EOL>

Return the suffix similarity of two strings.

        Suffix similarity is the ratio of the length of the shorter term that
        exactly matches the longer term to the length of the shorter term,
        beginning at the end of both terms.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Suffix similarity

        Examples
        --------
        >>> cmp = Suffix()
        >>> cmp.sim('cat', 'hat')
        0.6666666666666666
        >>> cmp.sim('Niall', 'Neil')
        0.25
        >>> cmp.sim('aluminum', 'Catalan')
        0.0
        >>> cmp.sim('ATCG', 'TAGC')
        0.0


def sim(self, src, tar, *args, **kwargs):

return <NUM_LIT:1.0> - self.dist(src, tar, *args, **kwargs)<EOL>

Return similarity.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        *args
            Variable length argument list.
        **kwargs
            Arbitrary keyword arguments.

        Returns
        -------
        float
            Similarity


def dist(self, src, tar, *args, **kwargs):

return <NUM_LIT:1.0> - self.sim(src, tar, *args, **kwargs)<EOL>

Return distance.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        *args
            Variable length argument list.
        **kwargs
            Arbitrary keyword arguments.

        Returns
        -------
        float
            Distance


def dist_abs(self, src, tar, *args, **kwargs):

return self.dist(src, tar, *args, **kwargs)<EOL>

Return absolute distance.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        *args
            Variable length argument list.
        **kwargs
            Arbitrary keyword arguments.

        Returns
        -------
        int
            Absolute distance


return NCDlzma().dist(src, tar)<EOL>

Return the NCD between two strings using LZMA compression.

    This is a wrapper for :py:meth:`NCDlzma.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison

    Returns
    -------
    float
        Compression distance

    Examples
    --------
    >>> dist_ncd_lzma('cat', 'hat')
    0.08695652173913043
    >>> dist_ncd_lzma('Niall', 'Neil')
    0.16
    >>> dist_ncd_lzma('aluminum', 'Catalan')
    0.16
    >>> dist_ncd_lzma('ATCG', 'TAGC')
    0.08695652173913043


return NCDlzma().sim(src, tar)<EOL>

Return the NCD similarity between two strings using LZMA compression.

    This is a wrapper for :py:meth:`NCDlzma.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison

    Returns
    -------
    float
        Compression similarity

    Examples
    --------
    >>> sim_ncd_lzma('cat', 'hat')
    0.9130434782608696
    >>> sim_ncd_lzma('Niall', 'Neil')
    0.84
    >>> sim_ncd_lzma('aluminum', 'Catalan')
    0.84
    >>> sim_ncd_lzma('ATCG', 'TAGC')
    0.9130434782608696


if src == tar:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>src = src.encode('<STR_LIT:utf-8>')<EOL>tar = tar.encode('<STR_LIT:utf-8>')<EOL>if lzma is not None:<EOL><INDENT>src_comp = lzma.compress(src)[<NUM_LIT>:]<EOL>tar_comp = lzma.compress(tar)[<NUM_LIT>:]<EOL>concat_comp = lzma.compress(src + tar)[<NUM_LIT>:]<EOL>concat_comp2 = lzma.compress(tar + src)[<NUM_LIT>:]<EOL><DEDENT>else:  <EOL><INDENT>raise ValueError(<EOL>'<STR_LIT>'<EOL>)<EOL><DEDENT>return (<EOL>min(len(concat_comp), len(concat_comp2))<EOL>- min(len(src_comp), len(tar_comp))<EOL>) / max(len(src_comp), len(tar_comp))<EOL>

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


def eudex_hamming(<EOL>src, tar, weights='<STR_LIT>', max_length=<NUM_LIT:8>, normalized=False<EOL>):

return Eudex().dist_abs(src, tar, weights, max_length, normalized)<EOL>

Calculate the Hamming distance between the Eudex hashes of two terms.

    This is a wrapper for :py:meth:`Eudex.eudex_hamming`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    weights : str, iterable, or generator function
        The weights or weights generator function
    max_length : int
        The number of characters to encode as a eudex hash
    normalized : bool
        Normalizes to [0, 1] if True

    Returns
    -------
    int
        The Eudex Hamming distance

    Examples
    --------
    >>> eudex_hamming('cat', 'hat')
    128
    >>> eudex_hamming('Niall', 'Neil')
    2
    >>> eudex_hamming('Colin', 'Cuilen')
    10
    >>> eudex_hamming('ATCG', 'TAGC')
    403

    >>> eudex_hamming('cat', 'hat', weights='fibonacci')
    34
    >>> eudex_hamming('Niall', 'Neil', weights='fibonacci')
    2
    >>> eudex_hamming('Colin', 'Cuilen', weights='fibonacci')
    7
    >>> eudex_hamming('ATCG', 'TAGC', weights='fibonacci')
    117

    >>> eudex_hamming('cat', 'hat', weights=None)
    1
    >>> eudex_hamming('Niall', 'Neil', weights=None)
    1
    >>> eudex_hamming('Colin', 'Cuilen', weights=None)
    2
    >>> eudex_hamming('ATCG', 'TAGC', weights=None)
    9

    >>> # Using the OEIS A000142:
    >>> eudex_hamming('cat', 'hat', [1, 1, 2, 6, 24, 120, 720, 5040])
    1
    >>> eudex_hamming('Niall', 'Neil', [1, 1, 2, 6, 24, 120, 720, 5040])
    720
    >>> eudex_hamming('Colin', 'Cuilen', [1, 1, 2, 6, 24, 120, 720, 5040])
    744
    >>> eudex_hamming('ATCG', 'TAGC', [1, 1, 2, 6, 24, 120, 720, 5040])
    6243


def dist_eudex(src, tar, weights='<STR_LIT>', max_length=<NUM_LIT:8>):

return Eudex().dist(src, tar, weights, max_length)<EOL>

Return normalized Hamming distance between Eudex hashes of two terms.

    This is a wrapper for :py:meth:`Eudex.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    weights : str, iterable, or generator function
        The weights or weights generator function
    max_length : int
        The number of characters to encode as a eudex hash

    Returns
    -------
    int
        The normalized Eudex Hamming distance

    Examples
    --------
    >>> round(dist_eudex('cat', 'hat'), 12)
    0.062745098039
    >>> round(dist_eudex('Niall', 'Neil'), 12)
    0.000980392157
    >>> round(dist_eudex('Colin', 'Cuilen'), 12)
    0.004901960784
    >>> round(dist_eudex('ATCG', 'TAGC'), 12)
    0.197549019608


def sim_eudex(src, tar, weights='<STR_LIT>', max_length=<NUM_LIT:8>):

return Eudex().sim(src, tar, weights, max_length)<EOL>

Return normalized Hamming similarity between Eudex hashes of two terms.

    This is a wrapper for :py:meth:`Eudex.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    weights : str, iterable, or generator function
        The weights or weights generator function
    max_length : int
        The number of characters to encode as a eudex hash

    Returns
    -------
    int
        The normalized Eudex Hamming similarity

    Examples
    --------
    >>> round(sim_eudex('cat', 'hat'), 12)
    0.937254901961
    >>> round(sim_eudex('Niall', 'Neil'), 12)
    0.999019607843
    >>> round(sim_eudex('Colin', 'Cuilen'), 12)
    0.995098039216
    >>> round(sim_eudex('ATCG', 'TAGC'), 12)
    0.802450980392


num_a, num_b = <NUM_LIT:1>, <NUM_LIT:2><EOL>while True:<EOL><INDENT>yield num_a<EOL>num_a, num_b = num_b, num_a + num_b<EOL><DEDENT>

Yield the next Fibonacci number.

        Based on https://www.python-course.eu/generators.php
        Starts at Fibonacci number 3 (the second 1)

        Yields
        ------
        int
            The next Fibonacci number


exp = <NUM_LIT:0><EOL>while True:<EOL><INDENT>yield base ** exp<EOL>exp += <NUM_LIT:1><EOL><DEDENT>

Yield the next value in an exponential series of the base.

        Starts at base**0

        Parameters
        ----------
        base : int
            The base to exponentiate

        Yields
        ------
        int
            The next power of `base`


def dist_abs(<EOL>self, src, tar, weights='<STR_LIT>', max_length=<NUM_LIT:8>, normalized=False<EOL>):

<EOL>xored = eudex(src, max_length=max_length) ^ eudex(<EOL>tar, max_length=max_length<EOL>)<EOL>if not weights:<EOL><INDENT>binary = bin(xored)<EOL>distance = binary.count('<STR_LIT:1>')<EOL>if normalized:<EOL><INDENT>return distance / (len(binary) - <NUM_LIT:2>)<EOL><DEDENT>return distance<EOL><DEDENT>if callable(weights):<EOL><INDENT>weights = weights()<EOL><DEDENT>elif weights == '<STR_LIT>':<EOL><INDENT>weights = Eudex.gen_exponential()<EOL><DEDENT>elif weights == '<STR_LIT>':<EOL><INDENT>weights = Eudex.gen_fibonacci()<EOL><DEDENT>if isinstance(weights, GeneratorType):<EOL><INDENT>weights = [next(weights) for _ in range(max_length)][::-<NUM_LIT:1>]<EOL><DEDENT>distance = <NUM_LIT:0><EOL>max_distance = <NUM_LIT:0><EOL>while (xored or normalized) and weights:<EOL><INDENT>max_distance += <NUM_LIT:8> * weights[-<NUM_LIT:1>]<EOL>distance += bin(xored & <NUM_LIT>).count('<STR_LIT:1>') * weights.pop()<EOL>xored >>= <NUM_LIT:8><EOL><DEDENT>if normalized:<EOL><INDENT>distance /= max_distance<EOL><DEDENT>return distance<EOL>

Calculate the distance between the Eudex hashes of two terms.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        weights : str, iterable, or generator function
            The weights or weights generator function

                - If set to ``None``, a simple Hamming distance is calculated.
                - If set to ``exponential``, weight decays by powers of 2, as
                  proposed in the eudex specification:
                  https://github.com/ticki/eudex.
                - If set to ``fibonacci``, weight decays through the Fibonacci
                  series, as in the eudex reference implementation.
                - If set to a callable function, this assumes it creates a
                  generator and the generator is used to populate a series of
                  weights.
                - If set to an iterable, the iterable's values should be
                  integers and will be used as the weights.

        max_length : int
            The number of characters to encode as a eudex hash
        normalized : bool
            Normalizes to [0, 1] if True

        Returns
        -------
        int
            The Eudex Hamming distance

        Examples
        --------
        >>> cmp = Eudex()
        >>> cmp.dist_abs('cat', 'hat')
        128
        >>> cmp.dist_abs('Niall', 'Neil')
        2
        >>> cmp.dist_abs('Colin', 'Cuilen')
        10
        >>> cmp.dist_abs('ATCG', 'TAGC')
        403

        >>> cmp.dist_abs('cat', 'hat', weights='fibonacci')
        34
        >>> cmp.dist_abs('Niall', 'Neil', weights='fibonacci')
        2
        >>> cmp.dist_abs('Colin', 'Cuilen', weights='fibonacci')
        7
        >>> cmp.dist_abs('ATCG', 'TAGC', weights='fibonacci')
        117

        >>> cmp.dist_abs('cat', 'hat', weights=None)
        1
        >>> cmp.dist_abs('Niall', 'Neil', weights=None)
        1
        >>> cmp.dist_abs('Colin', 'Cuilen', weights=None)
        2
        >>> cmp.dist_abs('ATCG', 'TAGC', weights=None)
        9

        >>> # Using the OEIS A000142:
        >>> cmp.dist_abs('cat', 'hat', [1, 1, 2, 6, 24, 120, 720, 5040])
        1
        >>> cmp.dist_abs('Niall', 'Neil', [1, 1, 2, 6, 24, 120, 720, 5040])
        720
        >>> cmp.dist_abs('Colin', 'Cuilen',
        ... [1, 1, 2, 6, 24, 120, 720, 5040])
        744
        >>> cmp.dist_abs('ATCG', 'TAGC', [1, 1, 2, 6, 24, 120, 720, 5040])
        6243


def dist(self, src, tar, weights='<STR_LIT>', max_length=<NUM_LIT:8>):

return self.dist_abs(src, tar, weights, max_length, True)<EOL>

Return normalized distance between the Eudex hashes of two terms.

        This is Eudex distance normalized to [0, 1].

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        weights : str, iterable, or generator function
            The weights or weights generator function
        max_length : int
            The number of characters to encode as a eudex hash

        Returns
        -------
        int
            The normalized Eudex Hamming distance

        Examples
        --------
        >>> cmp = Eudex()
        >>> round(cmp.dist('cat', 'hat'), 12)
        0.062745098039
        >>> round(cmp.dist('Niall', 'Neil'), 12)
        0.000980392157
        >>> round(cmp.dist('Colin', 'Cuilen'), 12)
        0.004901960784
        >>> round(cmp.dist('ATCG', 'TAGC'), 12)
        0.197549019608


def sim_dice(src, tar, qval=<NUM_LIT:2>):

return Dice().sim(src, tar, qval)<EOL>

Return the Sørensen–Dice coefficient of two strings.

    This is a wrapper for :py:meth:`Dice.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

    Returns
    -------
    float
        Sørensen–Dice similarity

    Examples
    --------
    >>> sim_dice('cat', 'hat')
    0.5
    >>> sim_dice('Niall', 'Neil')
    0.36363636363636365
    >>> sim_dice('aluminum', 'Catalan')
    0.11764705882352941
    >>> sim_dice('ATCG', 'TAGC')
    0.0


def dist_dice(src, tar, qval=<NUM_LIT:2>):

return Dice().dist(src, tar, qval)<EOL>

Return the Sørensen–Dice distance between two strings.

    This is a wrapper for :py:meth:`Dice.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

    Returns
    -------
    float
        Sørensen–Dice distance

    Examples
    --------
    >>> dist_dice('cat', 'hat')
    0.5
    >>> dist_dice('Niall', 'Neil')
    0.6363636363636364
    >>> dist_dice('aluminum', 'Catalan')
    0.8823529411764706
    >>> dist_dice('ATCG', 'TAGC')
    1.0


def sim(self, src, tar, qval=<NUM_LIT:2>):

return super(self.__class__, self).sim(src, tar, qval, <NUM_LIT:0.5>, <NUM_LIT:0.5>)<EOL>

Return the Sørensen–Dice coefficient 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
            Sørensen–Dice similarity

        Examples
        --------
        >>> cmp = Dice()
        >>> cmp.sim('cat', 'hat')
        0.5
        >>> cmp.sim('Niall', 'Neil')
        0.36363636363636365
        >>> cmp.sim('aluminum', 'Catalan')
        0.11764705882352941
        >>> cmp.sim('ATCG', 'TAGC')
        0.0


def sim_jaccard(src, tar, qval=<NUM_LIT:2>):

return Jaccard().sim(src, tar, qval)<EOL>

Return the Jaccard similarity of two strings.

    This is a wrapper for :py:meth:`Jaccard.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

    Returns
    -------
    float
        Jaccard similarity

    Examples
    --------
    >>> sim_jaccard('cat', 'hat')
    0.3333333333333333
    >>> sim_jaccard('Niall', 'Neil')
    0.2222222222222222
    >>> sim_jaccard('aluminum', 'Catalan')
    0.0625
    >>> sim_jaccard('ATCG', 'TAGC')
    0.0


def dist_jaccard(src, tar, qval=<NUM_LIT:2>):

return Jaccard().dist(src, tar, qval)<EOL>

Return the Jaccard distance between two strings.

    This is a wrapper for :py:meth:`Jaccard.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

    Returns
    -------
    float
        Jaccard distance

    Examples
    --------
    >>> dist_jaccard('cat', 'hat')
    0.6666666666666667
    >>> dist_jaccard('Niall', 'Neil')
    0.7777777777777778
    >>> dist_jaccard('aluminum', 'Catalan')
    0.9375
    >>> dist_jaccard('ATCG', 'TAGC')
    1.0


def tanimoto(src, tar, qval=<NUM_LIT:2>):

return Jaccard().tanimoto_coeff(src, tar, qval)<EOL>

Return the Tanimoto coefficient of two strings.

    This is a wrapper for :py:meth:`Jaccard.tanimoto_coeff`.

    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
        Tanimoto distance

    Examples
    --------
    >>> tanimoto('cat', 'hat')
    -1.5849625007211563
    >>> tanimoto('Niall', 'Neil')
    -2.1699250014423126
    >>> tanimoto('aluminum', 'Catalan')
    -4.0
    >>> tanimoto('ATCG', 'TAGC')
    -inf


return super(self.__class__, self).sim(src, tar, qval, <NUM_LIT:1>, <NUM_LIT:1>)<EOL>

r"""Return the Jaccard 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
            Jaccard similarity

        Examples
        --------
        >>> cmp = Jaccard()
        >>> cmp.sim('cat', 'hat')
        0.3333333333333333
        >>> cmp.sim('Niall', 'Neil')
        0.2222222222222222
        >>> cmp.sim('aluminum', 'Catalan')
        0.0625
        >>> cmp.sim('ATCG', 'TAGC')
        0.0


def tanimoto_coeff(self, src, tar, qval=<NUM_LIT:2>):

coeff = self.sim(src, tar, qval)<EOL>if coeff != <NUM_LIT:0>:<EOL><INDENT>return log(coeff, <NUM_LIT:2>)<EOL><DEDENT>return float('<STR_LIT>')<EOL>

Return the Tanimoto distance between two strings.

        Tanimoto distance :cite:`Tanimoto:1958` is
        :math:`-log_{2} sim_{Tanimoto}(X, Y)`.

        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
            Tanimoto distance

        Examples
        --------
        >>> cmp = Jaccard()
        >>> cmp.tanimoto_coeff('cat', 'hat')
        -1.5849625007211563
        >>> cmp.tanimoto_coeff('Niall', 'Neil')
        -2.1699250014423126
        >>> cmp.tanimoto_coeff('aluminum', 'Catalan')
        -4.0
        >>> cmp.tanimoto_coeff('ATCG', 'TAGC')
        -inf


def sift4_common(src, tar, max_offset=<NUM_LIT:5>, max_distance=<NUM_LIT:0>):

return Sift4().dist_abs(src, tar, max_offset, max_distance)<EOL>

Return the "common" Sift4 distance between two terms.

    This is a wrapper for :py:meth:`Sift4.dist_abs`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    max_offset : int
        The number of characters to search for matching letters
    max_distance : int
        The distance at which to stop and exit

    Returns
    -------
    int
        The Sift4 distance according to the common formula

    Examples
    --------
    >>> sift4_common('cat', 'hat')
    1
    >>> sift4_common('Niall', 'Neil')
    2
    >>> sift4_common('Colin', 'Cuilen')
    3
    >>> sift4_common('ATCG', 'TAGC')
    2


def dist_sift4(src, tar, max_offset=<NUM_LIT:5>, max_distance=<NUM_LIT:0>):

return Sift4().dist(src, tar, max_offset, max_distance)<EOL>

Return the normalized "common" Sift4 distance between two terms.

    This is a wrapper for :py:meth:`Sift4.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    max_offset : int
        The number of characters to search for matching letters
    max_distance : int
        The distance at which to stop and exit

    Returns
    -------
    float
        The normalized Sift4 distance

    Examples
    --------
    >>> round(dist_sift4('cat', 'hat'), 12)
    0.333333333333
    >>> dist_sift4('Niall', 'Neil')
    0.4
    >>> dist_sift4('Colin', 'Cuilen')
    0.5
    >>> dist_sift4('ATCG', 'TAGC')
    0.5


def sim_sift4(src, tar, max_offset=<NUM_LIT:5>, max_distance=<NUM_LIT:0>):

return Sift4().sim(src, tar, max_offset, max_distance)<EOL>

Return the normalized "common" Sift4 similarity of two terms.

    This is a wrapper for :py:meth:`Sift4.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    max_offset : int
        The number of characters to search for matching letters
    max_distance : int
        The distance at which to stop and exit

    Returns
    -------
    float
        The normalized Sift4 similarity

    Examples
    --------
    >>> round(sim_sift4('cat', 'hat'), 12)
    0.666666666667
    >>> sim_sift4('Niall', 'Neil')
    0.6
    >>> sim_sift4('Colin', 'Cuilen')
    0.5
    >>> sim_sift4('ATCG', 'TAGC')
    0.5


def dist_abs(self, src, tar, max_offset=<NUM_LIT:5>, max_distance=<NUM_LIT:0>):

if not src:<EOL><INDENT>return len(tar)<EOL><DEDENT>if not tar:<EOL><INDENT>return len(src)<EOL><DEDENT>src_len = len(src)<EOL>tar_len = len(tar)<EOL>src_cur = <NUM_LIT:0><EOL>tar_cur = <NUM_LIT:0><EOL>lcss = <NUM_LIT:0><EOL>local_cs = <NUM_LIT:0><EOL>trans = <NUM_LIT:0><EOL>offset_arr = []<EOL>while (src_cur < src_len) and (tar_cur < tar_len):<EOL><INDENT>if src[src_cur] == tar[tar_cur]:<EOL><INDENT>local_cs += <NUM_LIT:1><EOL>is_trans = False<EOL>i = <NUM_LIT:0><EOL>while i < len(offset_arr):<EOL><INDENT>ofs = offset_arr[i]<EOL>if src_cur <= ofs['<STR_LIT>'] or tar_cur <= ofs['<STR_LIT>']:<EOL><INDENT>is_trans = abs(tar_cur - src_cur) >= abs(<EOL>ofs['<STR_LIT>'] - ofs['<STR_LIT>']<EOL>)<EOL>if is_trans:<EOL><INDENT>trans += <NUM_LIT:1><EOL><DEDENT>elif not ofs['<STR_LIT>']:<EOL><INDENT>ofs['<STR_LIT>'] = True<EOL>trans += <NUM_LIT:1><EOL><DEDENT>break<EOL><DEDENT>elif src_cur > ofs['<STR_LIT>'] and tar_cur > ofs['<STR_LIT>']:<EOL><INDENT>del offset_arr[i]<EOL><DEDENT>else:<EOL><INDENT>i += <NUM_LIT:1><EOL><DEDENT><DEDENT>offset_arr.append(<EOL>{'<STR_LIT>': src_cur, '<STR_LIT>': tar_cur, '<STR_LIT>': is_trans}<EOL>)<EOL><DEDENT>else:<EOL><INDENT>lcss += local_cs<EOL>local_cs = <NUM_LIT:0><EOL>if src_cur != tar_cur:<EOL><INDENT>src_cur = tar_cur = min(src_cur, tar_cur)<EOL><DEDENT>for i in range(max_offset):<EOL><INDENT>if not (<EOL>(src_cur + i < src_len) or (tar_cur + i < tar_len)<EOL>):<EOL><INDENT>break<EOL><DEDENT>if (src_cur + i < src_len) and (<EOL>src[src_cur + i] == tar[tar_cur]<EOL>):<EOL><INDENT>src_cur += i - <NUM_LIT:1><EOL>tar_cur -= <NUM_LIT:1><EOL>break<EOL><DEDENT>if (tar_cur + i < tar_len) and (<EOL>src[src_cur] == tar[tar_cur + i]<EOL>):<EOL><INDENT>src_cur -= <NUM_LIT:1><EOL>tar_cur += i - <NUM_LIT:1><EOL>break<EOL><DEDENT><DEDENT><DEDENT>src_cur += <NUM_LIT:1><EOL>tar_cur += <NUM_LIT:1><EOL>if max_distance:<EOL><INDENT>temporary_distance = max(src_cur, tar_cur) - lcss + trans<EOL>if temporary_distance >= max_distance:<EOL><INDENT>return round(temporary_distance)<EOL><DEDENT><DEDENT>if (src_cur >= src_len) or (tar_cur >= tar_len):<EOL><INDENT>lcss += local_cs<EOL>local_cs = <NUM_LIT:0><EOL>src_cur = tar_cur = min(src_cur, tar_cur)<EOL><DEDENT><DEDENT>lcss += local_cs<EOL>return round(max(src_len, tar_len) - lcss + trans)<EOL>

Return the "common" Sift4 distance between two terms.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        max_offset : int
            The number of characters to search for matching letters
        max_distance : int
            The distance at which to stop and exit

        Returns
        -------
        int
            The Sift4 distance according to the common formula

        Examples
        --------
        >>> cmp = Sift4()
        >>> cmp.dist_abs('cat', 'hat')
        1
        >>> cmp.dist_abs('Niall', 'Neil')
        2
        >>> cmp.dist_abs('Colin', 'Cuilen')
        3
        >>> cmp.dist_abs('ATCG', 'TAGC')
        2


def dist(self, src, tar, max_offset=<NUM_LIT:5>, max_distance=<NUM_LIT:0>):

return self.dist_abs(src, tar, max_offset, max_distance) / (<EOL>max(len(src), len(tar), <NUM_LIT:1>)<EOL>)<EOL>

Return the normalized "common" Sift4 distance between two terms.

        This is Sift4 distance, normalized to [0, 1].

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        max_offset : int
            The number of characters to search for matching letters
        max_distance : int
            The distance at which to stop and exit

        Returns
        -------
        float
            The normalized Sift4 distance

        Examples
        --------
        >>> cmp = Sift4()
        >>> round(cmp.dist('cat', 'hat'), 12)
        0.333333333333
        >>> cmp.dist('Niall', 'Neil')
        0.4
        >>> cmp.dist('Colin', 'Cuilen')
        0.5
        >>> cmp.dist('ATCG', 'TAGC')
        0.5


stripped = '<STR_LIT>'<EOL>for char in word:<EOL><INDENT>if char not in set('<STR_LIT>'):<EOL><INDENT>stripped += char<EOL><DEDENT><DEDENT>return stripped.strip()<EOL>

Return a word with punctuation stripped out.

        Parameters
        ----------
        word : str
            A word to strip punctuation from

        Returns
        -------
        str
            The word stripped of punctuation

        Examples
        --------
        >>> pe = Synoname()
        >>> pe._synoname_strip_punct('AB;CD EF-GH$IJ')
        'ABCD EFGHIJ'


def _synoname_word_approximation(<EOL>self, src_ln, tar_ln, src_fn='<STR_LIT>', tar_fn='<STR_LIT>', features=None<EOL>):

if features is None:<EOL><INDENT>features = {}<EOL><DEDENT>if '<STR_LIT>' not in features:<EOL><INDENT>features['<STR_LIT>'] = []<EOL><DEDENT>if '<STR_LIT>' not in features:<EOL><INDENT>features['<STR_LIT>'] = []<EOL><DEDENT>src_len_specials = len(features['<STR_LIT>'])<EOL>tar_len_specials = len(features['<STR_LIT>'])<EOL>if ('<STR_LIT>' in features and features['<STR_LIT>']) or (<EOL>'<STR_LIT>' in features and features['<STR_LIT>']<EOL>):<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>full_tar1 = '<STR_LIT:U+0020>'.join((tar_ln, tar_fn)).replace('<STR_LIT:->', '<STR_LIT:U+0020>').strip()<EOL>for s_pos, s_type in features['<STR_LIT>']:<EOL><INDENT>if s_type == '<STR_LIT:a>':<EOL><INDENT>full_tar1 = full_tar1[<EOL>: -(<EOL><NUM_LIT:1><EOL>+ len(<EOL>self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>)<EOL>)<EOL>]<EOL><DEDENT>elif s_type == '<STR_LIT:b>':<EOL><INDENT>loc = (<EOL>full_tar1.find(<EOL>'<STR_LIT:U+0020>'<EOL>+ self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>+ '<STR_LIT:U+0020>'<EOL>)<EOL>+ <NUM_LIT:1><EOL>)<EOL>full_tar1 = (<EOL>full_tar1[:loc]<EOL>+ full_tar1[<EOL>loc<EOL>+ len(<EOL>self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>) :<EOL>]<EOL>)<EOL><DEDENT>elif s_type == '<STR_LIT:c>':<EOL><INDENT>full_tar1 = full_tar1[<EOL><NUM_LIT:1><EOL>+ len(<EOL>self._stc._synoname_special_table[s_pos][  <EOL><NUM_LIT:1><EOL>]<EOL>) :<EOL>]<EOL><DEDENT><DEDENT>full_src1 = '<STR_LIT:U+0020>'.join((src_ln, src_fn)).replace('<STR_LIT:->', '<STR_LIT:U+0020>').strip()<EOL>for s_pos, s_type in features['<STR_LIT>']:<EOL><INDENT>if s_type == '<STR_LIT:a>':<EOL><INDENT>full_src1 = full_src1[<EOL>: -(<EOL><NUM_LIT:1><EOL>+ len(<EOL>self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>)<EOL>)<EOL>]<EOL><DEDENT>elif s_type == '<STR_LIT:b>':<EOL><INDENT>loc = (<EOL>full_src1.find(<EOL>'<STR_LIT:U+0020>'<EOL>+ self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>+ '<STR_LIT:U+0020>'<EOL>)<EOL>+ <NUM_LIT:1><EOL>)<EOL>full_src1 = (<EOL>full_src1[:loc]<EOL>+ full_src1[<EOL>loc<EOL>+ len(<EOL>self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>) :<EOL>]<EOL>)<EOL><DEDENT>elif s_type == '<STR_LIT:c>':<EOL><INDENT>full_src1 = full_src1[<EOL><NUM_LIT:1><EOL>+ len(<EOL>self._stc._synoname_special_table[s_pos][  <EOL><NUM_LIT:1><EOL>]<EOL>) :<EOL>]<EOL><DEDENT><DEDENT>full_tar2 = full_tar1<EOL>for s_pos, s_type in features['<STR_LIT>']:<EOL><INDENT>if s_type == '<STR_LIT:d>':<EOL><INDENT>full_tar2 = full_tar2[<EOL>len(<EOL>self._stc._synoname_special_table[s_pos][  <EOL><NUM_LIT:1><EOL>]<EOL>) :<EOL>]<EOL><DEDENT>elif (<EOL>s_type == '<STR_LIT:X>'<EOL>and self._stc._synoname_special_table[s_pos][<NUM_LIT:1>]  <EOL>in full_tar2<EOL>):<EOL><INDENT>loc = full_tar2.find(<EOL>'<STR_LIT:U+0020>'<EOL>+ self._stc._synoname_special_table[s_pos][<NUM_LIT:1>]  <EOL>)<EOL>full_tar2 = (<EOL>full_tar2[:loc]<EOL>+ full_tar2[<EOL>loc<EOL>+ len(<EOL>self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>) :<EOL>]<EOL>)<EOL><DEDENT><DEDENT>full_src2 = full_src1<EOL>for s_pos, s_type in features['<STR_LIT>']:<EOL><INDENT>if s_type == '<STR_LIT:d>':<EOL><INDENT>full_src2 = full_src2[<EOL>len(<EOL>self._stc._synoname_special_table[s_pos][  <EOL><NUM_LIT:1><EOL>]<EOL>) :<EOL>]<EOL><DEDENT>elif (<EOL>s_type == '<STR_LIT:X>'<EOL>and self._stc._synoname_special_table[s_pos][<NUM_LIT:1>]  <EOL>in full_src2<EOL>):<EOL><INDENT>loc = full_src2.find(<EOL>'<STR_LIT:U+0020>'<EOL>+ self._stc._synoname_special_table[s_pos][<NUM_LIT:1>]  <EOL>)<EOL>full_src2 = (<EOL>full_src2[:loc]<EOL>+ full_src2[<EOL>loc<EOL>+ len(<EOL>self._stc._synoname_special_table[  <EOL>s_pos<EOL>][<NUM_LIT:1>]<EOL>) :<EOL>]<EOL>)<EOL><DEDENT><DEDENT>full_tar1 = self._synoname_strip_punct(full_tar1)<EOL>tar1_words = full_tar1.split()<EOL>tar1_num_words = len(tar1_words)<EOL>full_src1 = self._synoname_strip_punct(full_src1)<EOL>src1_words = full_src1.split()<EOL>src1_num_words = len(src1_words)<EOL>full_tar2 = self._synoname_strip_punct(full_tar2)<EOL>tar2_words = full_tar2.split()<EOL>tar2_num_words = len(tar2_words)<EOL>full_src2 = self._synoname_strip_punct(full_src2)<EOL>src2_words = full_src2.split()<EOL>src2_num_words = len(src2_words)<EOL>if (<EOL>src1_num_words < <NUM_LIT:2><EOL>and src_len_specials == <NUM_LIT:0><EOL>and src2_num_words < <NUM_LIT:2><EOL>and tar_len_specials == <NUM_LIT:0><EOL>):<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>if (<EOL>tar1_num_words == <NUM_LIT:1><EOL>and src1_num_words == <NUM_LIT:1><EOL>and tar1_words[<NUM_LIT:0>] == src1_words[<NUM_LIT:0>]<EOL>):<EOL><INDENT>return <NUM_LIT:1><EOL><DEDENT>if tar1_num_words < <NUM_LIT:2> and tar_len_specials == <NUM_LIT:0>:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>last_found = False<EOL>for word in tar1_words:<EOL><INDENT>if src_ln.endswith(word) or word + '<STR_LIT:U+0020>' in src_ln:<EOL><INDENT>last_found = True<EOL><DEDENT><DEDENT>if not last_found:<EOL><INDENT>for word in src1_words:<EOL><INDENT>if tar_ln.endswith(word) or word + '<STR_LIT:U+0020>' in tar_ln:<EOL><INDENT>last_found = True<EOL><DEDENT><DEDENT><DEDENT>matches = <NUM_LIT:0><EOL>if last_found:<EOL><INDENT>for i, s_word in enumerate(src1_words):<EOL><INDENT>for j, t_word in enumerate(tar1_words):<EOL><INDENT>if s_word == t_word:<EOL><INDENT>src1_words[i] = '<STR_LIT:@>'<EOL>tar1_words[j] = '<STR_LIT:@>'<EOL>matches += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT><DEDENT>w_ratio = matches / max(tar1_num_words, src1_num_words)<EOL>if matches > <NUM_LIT:1> or (<EOL>matches == <NUM_LIT:1><EOL>and src1_num_words == <NUM_LIT:1><EOL>and tar1_num_words == <NUM_LIT:1><EOL>and (tar_len_specials > <NUM_LIT:0> or src_len_specials > <NUM_LIT:0>)<EOL>):<EOL><INDENT>return w_ratio<EOL><DEDENT>if (<EOL>tar2_num_words == <NUM_LIT:1><EOL>and src2_num_words == <NUM_LIT:1><EOL>and tar2_words[<NUM_LIT:0>] == src2_words[<NUM_LIT:0>]<EOL>):<EOL><INDENT>return <NUM_LIT:1><EOL><DEDENT>if tar2_num_words < <NUM_LIT:2> and tar_len_specials == <NUM_LIT:0>:  <EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>last_found = False<EOL>for word in tar2_words:<EOL><INDENT>if src_ln.endswith(word) or word + '<STR_LIT:U+0020>' in src_ln:<EOL><INDENT>last_found = True<EOL><DEDENT><DEDENT>if not last_found:<EOL><INDENT>for word in src2_words:<EOL><INDENT>if tar_ln.endswith(word) or word + '<STR_LIT:U+0020>' in tar_ln:<EOL><INDENT>last_found = True<EOL><DEDENT><DEDENT><DEDENT>if not last_found:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>matches = <NUM_LIT:0><EOL>if last_found:<EOL><INDENT>for i, s_word in enumerate(src2_words):<EOL><INDENT>for j, t_word in enumerate(tar2_words):<EOL><INDENT>if s_word == t_word:<EOL><INDENT>src2_words[i] = '<STR_LIT:@>'<EOL>tar2_words[j] = '<STR_LIT:@>'<EOL>matches += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT><DEDENT>w_ratio = matches / max(tar2_num_words, src2_num_words)<EOL>if matches > <NUM_LIT:1> or (<EOL>matches == <NUM_LIT:1><EOL>and src2_num_words == <NUM_LIT:1><EOL>and tar2_num_words == <NUM_LIT:1><EOL>and (tar_len_specials > <NUM_LIT:0> or src_len_specials > <NUM_LIT:0>)<EOL>):<EOL><INDENT>return w_ratio<EOL><DEDENT>return <NUM_LIT:0><EOL>

Return the Synoname word approximation score for two names.

        Parameters
        ----------
        src_ln : str
            Last name of the source
        tar_ln : str
            Last name of the target
        src_fn : str
            First name of the source (optional)
        tar_fn : str
            First name of the target (optional)
        features : dict
            A dict containing special features calculated using
            :py:class:`fingerprint.SynonameToolcode` (optional)

        Returns
        -------
        float
            The word approximation score

        Examples
        --------
        >>> pe = Synoname()
        >>> pe._synoname_word_approximation('Smith Waterman', 'Waterman',
        ... 'Tom Joe Bob', 'Tom Joe')
        0.6


def sim_cosine(src, tar, qval=<NUM_LIT:2>):

return Cosine().sim(src, tar, qval)<EOL>

r"""Return the cosine similarity of two strings.

    This is a wrapper for :py:meth:`Cosine.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

    Returns
    -------
    float
        Cosine similarity

    Examples
    --------
    >>> sim_cosine('cat', 'hat')
    0.5
    >>> sim_cosine('Niall', 'Neil')
    0.3651483716701107
    >>> sim_cosine('aluminum', 'Catalan')
    0.11785113019775793
    >>> sim_cosine('ATCG', 'TAGC')
    0.0


def dist_cosine(src, tar, qval=<NUM_LIT:2>):

return Cosine().dist(src, tar, qval)<EOL>

Return the cosine distance between two strings.

    This is a wrapper for :py:meth:`Cosine.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

    Returns
    -------
    float
        Cosine distance

    Examples
    --------
    >>> dist_cosine('cat', 'hat')
    0.5
    >>> dist_cosine('Niall', 'Neil')
    0.6348516283298893
    >>> dist_cosine('aluminum', 'Catalan')
    0.882148869802242
    >>> dist_cosine('ATCG', 'TAGC')
    1.0


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

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


def __init__(self, tp=<NUM_LIT:0>, tn=<NUM_LIT:0>, fp=<NUM_LIT:0>, fn=<NUM_LIT:0>):

if isinstance(tp, (tuple, list)):<EOL><INDENT>if len(tp) == <NUM_LIT:4>:<EOL><INDENT>self._tp = tp[<NUM_LIT:0>]<EOL>self._tn = tp[<NUM_LIT:1>]<EOL>self._fp = tp[<NUM_LIT:2>]<EOL>self._fn = tp[<NUM_LIT:3>]<EOL><DEDENT>else:<EOL><INDENT>raise AttributeError(<EOL>'<STR_LIT>'<EOL>+ '<STR_LIT>'<EOL>)<EOL><DEDENT><DEDENT>elif isinstance(tp, dict):<EOL><INDENT>if '<STR_LIT>' in tp:<EOL><INDENT>self._tp = tp['<STR_LIT>']<EOL><DEDENT>if '<STR_LIT>' in tp:<EOL><INDENT>self._tn = tp['<STR_LIT>']<EOL><DEDENT>if '<STR_LIT>' in tp:<EOL><INDENT>self._fp = tp['<STR_LIT>']<EOL><DEDENT>if '<STR_LIT>' in tp:<EOL><INDENT>self._fn = tp['<STR_LIT>']<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self._tp = tp<EOL>self._tn = tn<EOL>self._fp = fp<EOL>self._fn = fn<EOL><DEDENT>

Initialize ConfusionTable.

        Parameters
        ----------
        tp : int or a tuple, list, or dict
            True positives; If a tuple or list is supplied, it must include 4
            values in the order [tp, tn, fp, fn]. If a dict is supplied, it
            must have 4 keys, namely 'tp', 'tn', 'fp', & 'fn'.
        tn : int
            True negatives
        fp : int
            False positives
        fn : int
            False negatives

        Raises
        ------
        AttributeError
            ConfusionTable requires a 4-tuple when being created from a tuple.

        Examples
        --------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct == ConfusionTable((120, 60, 20, 30))
        True
        >>> ct == ConfusionTable([120, 60, 20, 30])
        True
        >>> ct == ConfusionTable({'tp': 120, 'tn': 60, 'fp': 20, 'fn': 30})
        True


if isinstance(other, ConfusionTable):<EOL><INDENT>if id(self) == id(other):<EOL><INDENT>return True<EOL><DEDENT>if (<EOL>self._tp == other.true_pos()<EOL>and self._tn == other.true_neg()<EOL>and self._fp == other.false_pos()<EOL>and self._fn == other.false_neg()<EOL>):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>elif isinstance(other, (tuple, list)):<EOL><INDENT>if (<EOL>self._tp == other[<NUM_LIT:0>]<EOL>and self._tn == other[<NUM_LIT:1>]<EOL>and self._fp == other[<NUM_LIT:2>]<EOL>and self._fn == other[<NUM_LIT:3>]<EOL>):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>elif isinstance(other, dict):<EOL><INDENT>if (<EOL>self._tp == other['<STR_LIT>']<EOL>and self._tn == other['<STR_LIT>']<EOL>and self._fp == other['<STR_LIT>']<EOL>and self._fn == other['<STR_LIT>']<EOL>):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>return False<EOL>

Perform eqality (==) comparison.

        Compares a ConfusionTable to another ConfusionTable or its equivalent
        in the form of a tuple, list, or dict.

        Parameters
        ----------
        other : ConfusionTable
            Another ConfusionTable object to compare to

        Returns
        -------
        bool
            True if two ConfusionTables are the same object or all four of
            their attributes are equal

        Examples
        --------
        >>> ct1 = ConfusionTable(120, 60, 20, 30)
        >>> ct2 = ConfusionTable(120, 60, 20, 30)
        >>> ct3 = ConfusionTable(60, 30, 10, 15)

        >>> ct1 == ct2
        True
        >>> ct1 == ct3
        False

        >>> ct1 != ct2
        False
        >>> ct1 != ct3
        True


return '<STR_LIT>'.format(<EOL>self._tp, self._tn, self._fp, self._fn<EOL>)<EOL>

Cast to str.

        Returns
        -------
        str
            A human-readable version of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> str(ct)
        'tp:120, tn:60, fp:20, fn:30'


return self._tp, self._tn, self._fp, self._fn<EOL>

Cast to tuple.

        Returns
        -------
        tuple
            The confusion table as a 4-tuple (tp, tn, fp, fn)

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.to_tuple()
        (120, 60, 20, 30)


return {'<STR_LIT>': self._tp, '<STR_LIT>': self._tn, '<STR_LIT>': self._fp, '<STR_LIT>': self._fn}<EOL>

Cast to dict.

        Returns
        -------
        dict
            The confusion table as a dict

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> import pprint
        >>> pprint.pprint(ct.to_dict())
        {'fn': 30, 'fp': 20, 'tn': 60, 'tp': 120}


return self._tp<EOL>

Return true positives.

        Returns
        -------
        int
            The true positives of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.true_pos()
        120


return self._tn<EOL>

Return true negatives.

        Returns
        -------
        int
            The true negatives of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.true_neg()
        60


return self._fp<EOL>

Return false positives.

        Returns
        -------
        int
            The false positives of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.false_pos()
        20


return self._fn<EOL>

Return false negatives.

        Returns
        -------
        int
            The false negatives of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.false_neg()
        30


return self._tp + self._tn<EOL>

Return correct population.

        Returns
        -------
        int
            The correct population of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.correct_pop()
        180


return self._fp + self._fn<EOL>

Return error population.

        Returns
        -------
        int
            The error population of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.error_pop()
        50


return self._tp + self._fn<EOL>

Return condition positive population.

        Returns
        -------
        int
            The condition positive population of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.cond_pos_pop()
        150


return self._fp + self._tn<EOL>

Return condition negative population.

        Returns
        -------
        int
            The condition negative population of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.cond_neg_pop()
        80


return self._tp + self._tn + self._fp + self._fn<EOL>

Return population, N.

        Returns
        -------
        int
            The population (N) of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.population()
        230


if self._tp + self._fp == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return self._tp / (self._tp + self._fp)<EOL>

r"""Return precision.

        Precision is defined as :math:`\frac{tp}{tp + fp}`

        AKA positive predictive value (PPV)

        Cf. https://en.wikipedia.org/wiki/Precision_and_recall

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Precision

        Returns
        -------
        float
            The precision of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.precision()
        0.8571428571428571


if self.population() == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>random_precision = self.cond_pos_pop() / self.population()<EOL>return self.precision() / random_precision<EOL>

r"""Return gain in precision.

        The gain in precision is defined as:
        :math:`G(precision) = \frac{precision}{random~ precision}`

        Cf. https://en.wikipedia.org/wiki/Gain_(information_retrieval)

        Returns
        -------
        float
            The gain in precision of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.precision_gain()
        1.3142857142857143


if self._tp + self._fn == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return self._tp / (self._tp + self._fn)<EOL>

r"""Return recall.

        Recall is defined as :math:`\frac{tp}{tp + fn}`

        AKA sensitivity

        AKA true positive rate (TPR)

        Cf. https://en.wikipedia.org/wiki/Precision_and_recall

        Cf. https://en.wikipedia.org/wiki/Sensitivity_(test)

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Recall

        Returns
        -------
        float
            The recall of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.recall()
        0.8


if self._tn + self._fp == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return self._tn / (self._tn + self._fp)<EOL>

r"""Return specificity.

        Specificity is defined as :math:`\frac{tn}{tn + fp}`

        AKA true negative rate (TNR)

        Cf. https://en.wikipedia.org/wiki/Specificity_(tests)

        Returns
        -------
        float
            The specificity of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.specificity()
        0.75


if self._tn + self._fn == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return self._tn / (self._tn + self._fn)<EOL>

r"""Return negative predictive value (NPV).

        NPV is defined as :math:`\frac{tn}{tn + fn}`

        Cf. https://en.wikipedia.org/wiki/Negative_predictive_value

        Returns
        -------
        float
            The negative predictive value of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.npv()
        0.6666666666666666


if self._fp + self._tn == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return self._fp / (self._fp + self._tn)<EOL>

r"""Return fall-out.

        Fall-out is defined as :math:`\frac{fp}{fp + tn}`

        AKA false positive rate (FPR)

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Fall-out

        Returns
        -------
        float
            The fall-out of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.fallout()
        0.25


if self._fp + self._tp == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return self._fp / (self._fp + self._tp)<EOL>

r"""Return false discovery rate (FDR).

        False discovery rate is defined as :math:`\frac{fp}{fp + tp}`

        Cf. https://en.wikipedia.org/wiki/False_discovery_rate

        Returns
        -------
        float
            The false discovery rate of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.fdr()
        0.14285714285714285


if self.population() == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>return (self._tp + self._tn) / self.population()<EOL>

r"""Return accuracy.

        Accuracy is defined as :math:`\frac{tp + tn}{population}`

        Cf. https://en.wikipedia.org/wiki/Accuracy

        Returns
        -------
        float
            The accuracy of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.accuracy()
        0.782608695652174


if self.population() == <NUM_LIT:0>:<EOL><INDENT>return float('<STR_LIT>')<EOL><DEDENT>random_accuracy = (self.cond_pos_pop() / self.population()) ** <NUM_LIT:2> + (<EOL>self.cond_neg_pop() / self.population()<EOL>) ** <NUM_LIT:2><EOL>return self.accuracy() / random_accuracy<EOL>

r"""Return gain in accuracy.

        The gain in accuracy is defined as:
        :math:`G(accuracy) = \frac{accuracy}{random~ accuracy}`

        Cf. https://en.wikipedia.org/wiki/Gain_(information_retrieval)

        Returns
        -------
        float
            The gain in accuracy of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.accuracy_gain()
        1.4325259515570934


return <NUM_LIT:0.5> * (self.recall() + self.specificity())<EOL>

r"""Return balanced accuracy.

        Balanced accuracy is defined as
        :math:`\frac{sensitivity + specificity}{2}`

        Cf. https://en.wikipedia.org/wiki/Accuracy

        Returns
        -------
        float
            The balanced accuracy of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.balanced_accuracy()
        0.775


return self.recall() + self.specificity() - <NUM_LIT:1><EOL>

Return informedness.

        Informedness is defined as :math:`sensitivity + specificity - 1`.

        AKA Youden's J statistic (:cite:`Youden:1950`)

        AKA DeltaP'

        Cf. https://en.wikipedia.org/wiki/Youden%27s_J_statistic

        Returns
        -------
        float
            The informedness of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.informedness()
        0.55


return self.precision() + self.npv() - <NUM_LIT:1><EOL>

Return markedness.

        Markedness is defined as :math:`precision + npv - 1`

        Returns
        -------
        float
            The markedness of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.markedness()
        0.5238095238095237


return amean((self.precision(), self.recall()))<EOL>

r"""Return arithmetic mean of precision & recall.

        The arithmetic mean of precision and recall is defined as:
        :math:`\frac{precision \cdot recall}{2}`

        Cf. https://en.wikipedia.org/wiki/Arithmetic_mean

        Returns
        -------
        float
            The arithmetic mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_amean()
        0.8285714285714285


return gmean((self.precision(), self.recall()))<EOL>

r"""Return geometric mean of precision & recall.

        The geometric mean of precision and recall is defined as:
        :math:`\sqrt{precision \cdot recall}`

        Cf. https://en.wikipedia.org/wiki/Geometric_mean

        Returns
        -------
        float
            The geometric mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_gmean()
        0.828078671210825


return hmean((self.precision(), self.recall()))<EOL>

r"""Return harmonic mean of precision & recall.

        The harmonic mean of precision and recall is defined as:
        :math:`\frac{2 \cdot precision \cdot recall}{precision + recall}`

        Cf. https://en.wikipedia.org/wiki/Harmonic_mean

        Returns
        -------
        float
            The harmonic mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_hmean()
        0.8275862068965516


return qmean((self.precision(), self.recall()))<EOL>

r"""Return quadratic mean of precision & recall.

        The quadratic mean of precision and recall is defined as:
        :math:`\sqrt{\frac{precision^{2} + recall^{2}}{2}}`

        Cf. https://en.wikipedia.org/wiki/Quadratic_mean

        Returns
        -------
        float
            The quadratic mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_qmean()
        0.8290638930598233


return cmean((self.precision(), self.recall()))<EOL>

r"""Return contraharmonic mean of precision & recall.

        The contraharmonic mean is:
        :math:`\frac{precision^{2} + recall^{2}}{precision + recall}`

        Cf. https://en.wikipedia.org/wiki/Contraharmonic_mean

        Returns
        -------
        float
            The contraharmonic mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_cmean()
        0.8295566502463055


precision = self.precision()<EOL>recall = self.recall()<EOL>if not precision or not recall:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>elif precision == recall:<EOL><INDENT>return precision<EOL><DEDENT>return (precision - recall) / (math.log(precision) - math.log(recall))<EOL>

r"""Return logarithmic mean of precision & recall.

        The logarithmic mean is:
        0 if either precision or recall is 0,
        the precision if they are equal,
        otherwise :math:`\frac{precision - recall}
        {ln(precision) - ln(recall)}`

        Cf. https://en.wikipedia.org/wiki/Logarithmic_mean

        Returns
        -------
        float
            The logarithmic mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_lmean()
        0.8282429171492667


return imean((self.precision(), self.recall()))<EOL>

r"""Return identric (exponential) mean of precision & recall.

        The identric mean is:
        precision if precision = recall,
        otherwise :math:`\frac{1}{e} \cdot
        \sqrt[precision - recall]{\frac{precision^{precision}}
        {recall^{recall}}}`

        Cf. https://en.wikipedia.org/wiki/Identric_mean

        Returns
        -------
        float
            The identric mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_imean()
        0.8284071826325543


return seiffert_mean((self.precision(), self.recall()))<EOL>

r"""Return Seiffert's mean of precision & recall.

        Seiffert's mean of precision and recall is:
        :math:`\frac{precision - recall}{4 \cdot arctan
        \sqrt{\frac{precision}{recall}} - \pi}`

        It is defined in :cite:`Seiffert:1993`.

        Returns
        -------
        float
            Seiffert's mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_seiffert_mean()
        0.8284071696048312


return lehmer_mean((self.precision(), self.recall()), exp)<EOL>

r"""Return Lehmer mean of precision & recall.

        The Lehmer mean is:
        :math:`\frac{precision^{exp} + recall^{exp}}
        {precision^{exp-1} + recall^{exp-1}}`

        Cf. https://en.wikipedia.org/wiki/Lehmer_mean

        Parameters
        ----------
        exp : float
            The exponent of the Lehmer mean

        Returns
        -------
        float
            The Lehmer mean for the given exponent of the confusion table's
            precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_lehmer_mean()
        0.8295566502463055


return heronian_mean((self.precision(), self.recall()))<EOL>

r"""Return Heronian mean of precision & recall.

        The Heronian mean of precision and recall is defined as:
        :math:`\frac{precision + \sqrt{precision \cdot recall} + recall}{3}`

        Cf. https://en.wikipedia.org/wiki/Heronian_mean

        Returns
        -------
        float
            The Heronian mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_heronian_mean()
        0.8284071761178939


return hoelder_mean((self.precision(), self.recall()), exp)<EOL>

r"""Return Hölder (power/generalized) mean of precision & recall.

        The power mean of precision and recall is defined as:
        :math:`\frac{1}{2} \cdot
        \sqrt[exp]{precision^{exp} + recall^{exp}}`
        for :math:`exp \ne 0`, and the geometric mean for :math:`exp = 0`

        Cf. https://en.wikipedia.org/wiki/Generalized_mean

        Parameters
        ----------
        exp : float
            The exponent of the Hölder mean

        Returns
        -------
        float
            The Hölder mean for the given exponent of the confusion table's
            precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_hoelder_mean()
        0.8290638930598233


return agmean((self.precision(), self.recall()))<EOL>

Return arithmetic-geometric mean of precision & recall.

        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

        Returns
        -------
        float
            The arithmetic-geometric mean of the confusion table's precision &
            recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_agmean()
        0.8283250315702829


return ghmean((self.precision(), self.recall()))<EOL>

Return geometric-harmonic mean of precision & recall.

        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

        Returns
        -------
        float
            The geometric-harmonic mean of the confusion table's precision &
            recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_ghmean()
        0.8278323841238441


return aghmean((self.precision(), self.recall()))<EOL>

Return arithmetic-geometric-harmonic mean of precision & recall.

        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`.

        Returns
        -------
        float
            The arithmetic-geometric-harmonic mean of the confusion table's
            precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.pr_aghmean()
        0.8280786712108288


if beta <= <NUM_LIT:0>:<EOL><INDENT>raise AttributeError('<STR_LIT>')<EOL><DEDENT>precision = self.precision()<EOL>recall = self.recall()<EOL>return (<EOL>(<NUM_LIT:1> + beta ** <NUM_LIT:2>)<EOL>* precision<EOL>* recall<EOL>/ ((beta ** <NUM_LIT:2> * precision) + recall)<EOL>)<EOL>

r"""Return :math:`F_{\beta}` score.

        :math:`F_{\beta}` for a positive real value :math:`\beta` "measures
        the effectiveness of retrieval with respect to a user who
        attaches :math:`\beta` times as much importance to recall as
        precision" (van Rijsbergen 1979)

        :math:`F_{\beta}` score is defined as:
        :math:`(1 + \beta^2) \cdot \frac{precision \cdot recall}
        {((\beta^2 \cdot precision) + recall)}`

        Cf. https://en.wikipedia.org/wiki/F1_score

        Parameters
        ----------
        beta : float
            The :math:`\beta` parameter in the above formula

        Returns
        -------
        float
            The :math:`F_{\beta}` of the confusion table

        Raises
        ------
        AttributeError
            Beta must be a positive real value

        Examples
        --------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.fbeta_score()
        0.8275862068965518
        >>> ct.fbeta_score(beta=0.1)
        0.8565371024734982


return self.fbeta_score(<NUM_LIT>)<EOL>

Return :math:`F_{2}`.

        The :math:`F_{2}` score emphasizes recall over precision in comparison
        to the :math:`F_{1}` score

        Cf. https://en.wikipedia.org/wiki/F1_score

        Returns
        -------
        float
            The :math:`F_{2}` of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.f2_score()
        0.8108108108108109


return self.fbeta_score(<NUM_LIT:0.5>)<EOL>

Return :math:`F_{0.5}` score.

        The :math:`F_{0.5}` score emphasizes precision over recall in
        comparison to the :math:`F_{1}` score

        Cf. https://en.wikipedia.org/wiki/F1_score

        Returns
        -------
        float
            The :math:`F_{0.5}` score of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.fhalf_score()
        0.8450704225352114


return <NUM_LIT:1> - self.fbeta_score(beta)<EOL>

r"""Return :math:`E`-score.

        This is Van Rijsbergen's effectiveness measure:
        :math:`E=1-F_{\beta}`.

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#F-measure

        Parameters
        ----------
        beta : float
            The :math:`\beta` parameter in the above formula

        Returns
        -------
        float
            The :math:`E`-score of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.e_score()
        0.17241379310344818


return self.pr_hmean()<EOL>

r"""Return :math:`F_{1}` score.

        :math:`F_{1}` score is the harmonic mean of precision and recall:
        :math:`2 \cdot \frac{precision \cdot recall}{precision + recall}`

        Cf. https://en.wikipedia.org/wiki/F1_score

        Returns
        -------
        float
            The :math:`F_{1}` of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.f1_score()
        0.8275862068965516


return self.pr_hmean()<EOL>

r"""Return :math:`F`-measure.

        :math:`F`-measure is the harmonic mean of precision and recall:
        :math:`2 \cdot \frac{precision \cdot recall}{precision + recall}`

        Cf. https://en.wikipedia.org/wiki/F1_score

        Returns
        -------
        float
            The math:`F`-measure of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.f_measure()
        0.8275862068965516


return self.pr_gmean()<EOL>

r"""Return G-measure.

        :math:`G`-measure is the geometric mean of precision and recall:
        :math:`\sqrt{precision \cdot recall}`

        This is identical to the Fowlkes–Mallows (FM) index for two
        clusters.

        Cf. https://en.wikipedia.org/wiki/F1_score#G-measure

        Cf. https://en.wikipedia.org/wiki/Fowlkes%E2%80%93Mallows_index

        Returns
        -------
        float
            The :math:`G`-measure of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.g_measure()
        0.828078671210825