
    v5`n^                     @   d dl mZ d dlmZ ddlmZmZ 	 d dl	Z	n# e
$ r dZ	Y nw xY wg dZ G d de          Z G d	 d
e          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z e            Z e            Z e            xZZ e            Z e            Z e            Z e            Z e            Z e            Z e            Z dS )    )defaultdict)zip_longest   )BaseBaseSimilarityN)HammingMLIPNSLevenshteinDamerauLevenshteinJaroJaroWinklerStrCmp95NeedlemanWunschGotohSmithWatermanhammingmlipnslevenshteindamerau_levenshteinjarojaro_winklerstrcmp95needleman_wunschgotohsmith_watermanc                        e Zd ZdZddZd ZdS )	r   z
    Compute the Hamming distance between the two or more sequences.
    The Hamming distance is the number of differing items in ordered sequences.

    https://en.wikipedia.org/wiki/Hamming_distance
    r   NFTc                 L    || _         |p| j        | _        || _        || _        d S N)qval_ident	test_functruncateexternal)selfr   r!   r"   r#   s        Blib/python3.11/site-packages/textdistance/algorithms/edit_based.py__init__zHamming.__init__#   s)    	"1dk      c                        j         | }  j        | }||S  j        rt          nt          }t           fd || D                       S )Nc                 &    g | ]} j         |  S  )r!   ).0esr$   s     r%   
<listcomp>z$Hamming.__call__.<locals>.<listcomp>1   s%    GGG++GGGr'   )_get_sequencesquick_answerr"   zipr   sum)r$   	sequencesresult_zips   `   r%   __call__zHamming.__call__)   sf    'D'3	""I.Mm4ssGGGGddI6FGGGHHHr'   )r   NFT)__name__
__module____qualname____doc__r&   r5   r*   r'   r%   r   r      sF         ! ! ! !I I I I Ir'   r   c                   ,    e Zd ZdZd	dZd Zd Zd ZdS )
r
   a  
    Compute the absolute Levenshtein distance between the two sequences.
    The Levenshtein distance is the minimum number of edit operations necessary
    for transforming one sequence into the other. The edit operations allowed are:

        * deletion:     ABC -> BC, AC, AB
        * insertion:    ABC -> ABCD, EABC, AEBC..
        * substitution: ABC -> ABE, ADC, FBC..

    https://en.wikipedia.org/wiki/Levenshtein_distance
    TODO: https://gist.github.com/kylebgorman/1081951/9b38b7743a3cb5167ab2c6608ac8eea7fc629dca
    r   NTc                 >    || _         |p| j        | _        || _        d S r   r   r    r!   r#   r$   r   r!   r#   s       r%   r&   zLevenshtein.__init__A   "    	"1dk r'   c           	         |r|st          |          t          |          z   S |                     |d         |d                   r | |d d         |d d                   S t           | |d d         |           | ||d d                             } | |d d         |d d                   }t          ||          dz   S )Nr   )lenr!   min)r$   s1s2dss        r%   
_recursivezLevenshtein._recursiveF   s     	% 	%r77SWW$$>>"R&"R&)) 	*43B3CRC))) DCRC"DRW
 

 DCRC"SbS'""1ayy1}r'   c                    t          |          dz   }t          |          dz   }d}t          rt          j        |          }nt          |          }t          d|          D ]}||gdg|dz
  z  z   }}t          d|          D ]f}||         dz   }	||dz
           dz   }
|                     ||dz
           ||dz
                     }||dz
           | z   }t          ||	|
          ||<   g|d         S )zp
        source:
        https://github.com/jamesturk/jellyfish/blob/master/jellyfish/_jellyfish.py#L18
        r   Nr   r@   )rA   numpyarangeranger!   rB   )r$   rC   rD   rowscolsprevcurrcdeletion	insertiondistedits                r%   _cicledzLevenshtein._cicledW   s   
 2ww{2ww{ 	,t$$CC++Cq$ 	8 	8AaSA3$(#33#D1d^^ 8 87Q;AJN	~~bQiAE;;AE{$h/T8Y77A8 2wr'   c                     |                      ||          \  }}|                     ||          }||S |                     ||          S r   )r.   r/   rV   r$   rC   rD   r3   s       r%   r5   zLevenshtein.__call__n   sO    $$R,,B""2r**M||B###r'   r   NT)r6   r7   r8   r9   r&   rG   rV   r5   r*   r'   r%   r
   r
   4   s_         ! ! ! !
  "  .$ $ $ $ $r'   r
   c                   ,    e Zd ZdZd	dZd Zd Zd ZdS )
r   a  
    Compute the absolute Damerau-Levenshtein distance between the two sequences.
    The Damerau-Levenshtein distance is the minimum number of edit operations necessary
    for transforming one sequence into the other. The edit operations allowed are:

        * deletion:      ABC -> BC, AC, AB
        * insertion:     ABC -> ABCD, EABC, AEBC..
        * substitution:  ABC -> ABE, ADC, FBC..
        * transposition: ABC -> ACB, BAC

    https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
    r   NTc                 >    || _         |p| j        | _        || _        d S r   r<   r=   s       r%   r&   zDamerauLevenshtein.__init__   r>   r'   c           	         t          j        t          |          dz   t          |          dz   gt           j                  }t	          dt          |          dz             D ]}|dz   ||         d<   t	          dt          |          dz             D ]}|dz   |d         |<   t          |          D ]\  }}t          |          D ]\  }}t          |                     ||                     }t          ||dz
           |         dz   ||         |dz
           dz   ||dz
           |dz
           |z             ||         |<   |r|s|                     |||dz
                     st          ||         |         ||dz
           |dz
           |z             ||         |<   ܌|t          |          dz
           t          |          dz
           S )Nr   dtyper@      )rI   zerosrA   intrK   	enumerater!   rB   	r$   rC   rD   rE   ijcs1cs2costs	            r%   _numpyzDamerauLevenshtein._numpy   s   KR1c"ggk2%)DDD r3r77Q;'' 	 	A1uAaDHHr3r77Q;'' 	 	A1uAbE!HHmm 	 	FAs#B--  3t~~c377788 a!eHQK!OaDQK!Oa!eHQUOd* !Q   ~~c2a!e955 aDGa!eHQUOd* !Q( R1~c"ggk**r'   c           
         i }t          dt          |          dz             D ]}|dz   ||df<   t          dt          |          dz             D ]}|dz   |d|f<   t          |          D ]\  }}t          |          D ]\  }}t          |                     ||                     }t          ||dz
  |f         dz   |||dz
  f         dz   ||dz
  |dz
  f         |z             |||f<   |r|sq|                     |||dz
                     s|                     ||dz
           |          st          |||f         ||dz
  |dz
  f         |z             |||f<   |t          |          dz
  t          |          dz
  f         S )za
        https://www.guyrutenberg.com/2008/12/15/damerau-levenshtein-distance-in-python/
        r@   r   r_   )rK   rA   rb   ra   r!   rB   rc   s	            r%   _pure_pythonzDamerauLevenshtein._pure_python   s     r3r77Q;'' 	 	A1uAaeHHr3r77Q;'' 	 	A1uAb!eHHmm 	 	FAs#B--  3t~~c377788 a!eQhK!OaQhK!Oa!eQUlOd* !Q$   ~~c2a!e955 ~~bQi55 adGa!eQUlOd* !Q$#, R1c"ggk)**r'   c                     |                      ||          \  }}|                     ||          }||S |                     ||          S r   )r.   r/   rk   rX   s       r%   r5   zDamerauLevenshtein.__call__   sS    $$R,,B""2r**M
   R(((r'   rY   )r6   r7   r8   r9   r&   ri   rk   r5   r*   r'   r%   r   r   x   sa         ! ! ! !
+ + +B#+ #+ #+J
) 
) 
) 
) 
)r'   r   c                   (    e Zd ZdZd
dZd ZddZd	S )r   a  
    Computes the Jaro-Winkler measure between two strings.
    The Jaro-Winkler measure is designed to capture cases where two strings
    have a low Jaro score, but share a prefix.
    and thus are likely to match.

    https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance
    https://github.com/Yomguithereal/talisman/blob/master/src/metrics/distance/jaro.js
    https://github.com/Yomguithereal/talisman/blob/master/src/metrics/distance/jaro-winkler.js
    FTr   c                 >    || _         || _        || _        || _        d S r   )r   long_tolerance
winklerizer#   )r$   ro   rp   r   r#   s        r%   r&   zJaroWinkler.__init__   s#    	,$ r'   c                     dS Nr   r*   r$   r2   s     r%   maximumzJaroWinkler.maximum       qr'   皙?c                    |                      ||          \  }}|                     ||          }||S t          |          }t          |          }|r|sdS t          ||          }|dz  dz
  }|dk     rd}dg|z  }	dg|z  }
d}t	          |          D ]i\  }}t          d||z
            }t          ||z   |dz
            }t          ||dz             D ]'}|
|         s||         |k    rdx|	|<   |
|<   |dz  } n(j|sdS dx}}t	          |	          D ]@\  }}|r9t          ||          D ]}|
|         r|dz   } n||         ||         k    r|dz  }A|dz  }||z  ||z  z   }|||z
  |z  z  }|dz  }| j        s|S |dk    s|dk    s|dk    r|S t          |d	          }d}||k     r?||         ||         k    r-||         r%|dz  }||k     r||         ||         k    r||         %|r|||z  d
|z
  z  z  }| j        r|d	k    r|S ||dz   k    sd|z  ||z   k     r|S ||z
  dz
  ||z   |dz  z
  dz   z  }|d
|z
  |z  z  }|S )N        r_   r   r   FT   ffffff?         ?)	r.   r/   rA   maxrb   rB   rK   rp   ro   )r$   rC   rD   prefix_weightr3   s1_lens2_lenmin_lensearch_ranges1_flagss2_flagscommon_charsrd   s1_chlowhire   ktrans_counts1_fweighttmps                         r%   r5   zJaroWinkler.__call__   sN   $$R,,B""2r**MRR 	V 	3ff%%1)!L7V#7V# !" 	 	HAua\)**CQ%vz22B3Q''  { r!u~~044HQK(1+ A%LE  	3 K ** 	% 	%GAt %q&))  A{ E a5BqE>>1$K &)>><+-==!  	MS==FaKK6Q;;M OO!ee1A2a5FA !ee1A2a5 	9a-'3<88F
 " 	gllM1q5  A$4w{$B$BMa!#!a%(?!(CD3<3&&r'   N)FTr   T)rv   r6   r7   r8   r9   r&   rt   r5   r*   r'   r%   r   r      s[        	 	! ! ! !  M M M M M Mr'   r   c                         e Zd Zd fd	Z xZS )r   Fr   Tc                 R    t                                          |d||           d S )NF)ro   rp   r   r#   )superr&   )r$   ro   r   r#   	__class__s       r%   r&   zJaro.__init__B  s:    )	 	 	
 	
 	
 	
 	
r'   )Fr   T)r6   r7   r8   r&   __classcell__)r   s   @r%   r   r   A  s=        
 
 
 
 
 
 
 
 
 
r'   r   c                   B    e Zd ZdZdZddZd Zd	 Zd
 Zd Z	d Z
d ZdS )r   a0  
    Computes the Needleman-Wunsch measure between two strings.
    The Needleman-Wunsch generalizes the Levenshtein distance and considers global
    alignment between two strings. Specifically, it is computed by assigning
    a score to each alignment between two input strings and choosing the
    score of the best alignment, that is, the maximal score.
    An alignment between two strings is a set of correspondences between the
    characters of between them, allowing for gaps.

    https://en.wikipedia.org/wiki/Needleman%E2%80%93Wunsch_algorithm
    Fr|   Nr   Tc                 \    || _         || _        |r|| _        n| j        | _        || _        d S r   )r   gap_costsim_funcr    r#   r$   r   r   r   r#   s        r%   r&   zNeedlemanWunsch.__init__Y  s5    	  	($DMM KDM r'   c                 X    t          t          t          |                     | j        z  S r   )r}   maprA   r   rs   s     r%   minimumzNeedlemanWunsch.minimumb  s$    CY''(((4=88r'   c                 F    t          t          t          |                    S r   )r}   r   rA   rs   s     r%   rt   zNeedlemanWunsch.maximume      3sI&&'''r'   c                     d | j         | z  S )z'Get distance between sequences
        r@   )
similarityrs   s     r%   distancezNeedlemanWunsch.distanceh  s     ODOY///r'   c                 `     | j         | } | j        | }|dk    rdS  | j        | |z
  ||z
  z  S )!Get distance from 0 to 1
        r   )r   rt   r   r$   r2   r   rt   s       r%   normalized_distancez#NeedlemanWunsch.normalized_distancem  sL     $,	*$,	*a<<1y)G3'8IJJr'   c                 `     | j         | } | j        | }|dk    rdS  | j        | |z
  |dz  z  S )r   r   r   r_   )r   rt   r   r   s       r%   normalized_similarityz%NeedlemanWunsch.normalized_similarityv  sK     $,	*$,	*a<<1+g5'A+FFr'   c                    t           st          d          |                     ||          \  }}t          j        t	          |          dz   t	          |          dz   ft           j                  }t          t	          |          dz             D ]}|| j        z   ||df<   t          t	          |          dz             D ]}|| j        z   |d|f<   t          |d          D ]\  }}t          |d          D ]l\  }}||dz
  |dz
  f         | 	                    ||          z   }||dz
  |f         | j        z
  }	|||dz
  f         | j        z
  }
t          ||	|
          |||f<   m||j        d         dz
  |j        d         dz
  f         S )Nz2Please, install numpy for Needleman-Wunsch measurer   r]   r   )rI   ImportErrorr.   r`   rA   floatrK   r   rb   r   r}   shape)r$   rC   rD   dist_matrd   re   c1c2matchdeleteinserts              r%   r5   zNeedlemanWunsch.__call__  s    	TRSSS$$R,,B ;WWq[#b''A+&+
 
 

 s2ww{## 	2 	2A 4=01HQTNNs2ww{## 	2 	2A 4=01HQTNNr1%% 	< 	<EAr"2q)) < <2 QA.r21F1FF!!a%(+dm;!!QU(+dm;!$UFF!;!;A	<
 q)A-x~a/@1/DDEEr'   r|   Nr   T)r6   r7   r8   r9   positiver&   r   rt   r   r   r   r5   r*   r'   r%   r   r   K  s        
 
 H! ! ! !9 9 9( ( (0 0 0
K K KG G GF F F F Fr'   r   c                   &    e Zd ZdZd	dZd Zd ZdS )
r   a  
    Computes the Smith-Waterman measure between two strings.
    The Smith-Waterman algorithm performs local sequence alignment;
    that is, for determining similar regions between two strings.
    Instead of looking at the total sequence, the Smith-Waterman algorithm compares
    segments of all possible lengths and optimizes the similarity measure.

    https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm
    https://github.com/Yomguithereal/talisman/blob/master/src/metrics/distance/smith-waterman.js
    r|   Nr   Tc                 L    || _         || _        |p| j        | _        || _        d S r   )r   r   r    r   r#   r   s        r%   r&   zSmithWaterman.__init__  s)    	  /DK r'   c                 F    t          t          t          |                    S r   rB   r   rA   rs   s     r%   rt   zSmithWaterman.maximum  r   r'   c                    t           st          d          |                     ||          \  }}|                     ||          }||S t          j        t          |          dz   t          |          dz   ft           j                  }t          |d          D ]\  }}t          |d          D ]m\  }}||dz
  |dz
  f         |                     ||          z   }	||dz
  |f         | j	        z
  }
|||dz
  f         | j	        z
  }t          d|	|
|          |||f<   n||j        d         dz
  |j        d         dz
  f         S )Nz0Please, install numpy for Smith-Waterman measurer   r]   startr   )rI   r   r.   r/   r`   rA   r   rb   r   r   r}   r   )r$   rC   rD   r3   r   rd   sc1re   sc2r   r   r   s               r%   r5   zSmithWaterman.__call__  sw    	RPQQQ$$R,,B""2r**M;WWq[#b''A+&+
 
 
  !,,, 		? 		?FAs#Ba000 ? ?3 !QA.sC1H1HH "!a%(+dm;!!QU(+dm;!$Qvv!>!>A? q)A-x~a/@1/DDEEr'   r   r   r*   r'   r%   r   r     sU        	 	! ! ! !( ( (F F F F Fr'   r   c                   ,    e Zd ZdZd
dZd Zd Zd	 ZdS )r   zGotoh score
    Gotoh's algorithm is essentially Needleman-Wunsch with affine gap
    penalties:
    https://www.cs.umd.edu/class/spring2003/cmsc838t/papers/gotoh1982.pdf
    r   皙?NTc                 j    || _         || _        || _        |r|| _        n| j        | _        || _        d S r   )r   gap_opengap_extr   r    r#   )r$   r   r   r   r   r#   s         r%   r&   zGotoh.__init__  s<    	  	($DMM KDM r'   c                 H    t          t          t          |                     S r   r   rs   s     r%   r   zGotoh.minimum  s    CY''((((r'   c                 F    t          t          t          |                    S r   r   rs   s     r%   rt   zGotoh.maximum  r   r'   c           
         t           st          d          |                     ||          \  }}t          |          }t          |          }t          j        |dz   |dz   ft           j                  }t          j        |dz   |dz   ft           j                  }t          j        |dz   |dz   ft           j                  }d|d<   t          d          |d<   t          d          |d<   t          d|dz             D ]R}t          d          ||df<   | j         | j        |dz
  z  z
  ||df<   t          d          ||df<   | j         ||df<   St          d|dz             D ]R}	t          d          |d|	f<   t          d          |d|	f<   | j         |d|	f<   | j         | j        |	dz
  z  z
  |d|	f<   St          |d          D ]\  }}
t          |d          D ]\  }	}| 
                    |
|          }t          ||dz
  |	dz
  f         |z   ||dz
  |	dz
  f         |z   ||dz
  |	dz
  f         |z             |||	f<   t          ||dz
  |	f         | j        z
  ||dz
  |	f         | j        z
            |||	f<   t          |||	dz
  f         | j        z
  |||	dz
  f         | j        z
            |||	f<   یd |j        D             \  }}	t          |||	f         |||	f         |||	f                   S )	Nz'Please, install numpy for Gotoh measurer   r]   r   )r   r   z-infr   c              3       K   | ]	}|d z
  V  
dS )r   Nr*   )r+   ns     r%   	<genexpr>z!Gotoh.__call__.<locals>.<genexpr>  s&      ++!A++++++r'   )rI   r   r.   rA   r`   r   rK   r   r   rb   r   r}   r   )r$   rC   rD   len_s1len_s2d_matp_matq_matrd   re   r   r   sim_vals                r%   r5   zGotoh.__call__  sV    	IGHHH$$R,,B RRVaZ!4EKHHHVaZ!4EKHHHVaZ!4EKHHHdFmmdFmmdq&1*%% 	) 	)A--E!Q$K=.4<1q5+AAE!Q$K--E!Q$K=.E!Q$KKq&1*%% 	B 	BA--E!Q$K--E!Q$K=.E!Q$K=.4<1q5+AAE!Q$KK!,,, 	 	FAs#Ba000  3--S11!!a%Q,''1!a%Q,''1!a%Q,''1 ad
 "!a%(Odm3!a%(Odl2 ad "!QU(Odm3!QU(Odl2 ad  ,+u{+++15A;adU1a4[999r'   )r   r   Nr   T)r6   r7   r8   r9   r&   r   rt   r5   r*   r'   r%   r   r     s_         
! ! ! !) ) )( ( (0: 0: 0: 0: 0:r'   r   c                   @    e Zd ZdZdZd
dZd Zed             Zd Z	d	S )r   z`strcmp95 similarity

    http://cpansearch.perl.org/src/SCW/Text-JaroWinkler-0.1/strcmp95.c
    )$)AE)r   I)r   O)r   U)BV)r   r   )r   r   )r   r   )r   r   )r   r   )r   r   )r   Y)r   r   )CG)r   F)Wr   )r   r   )XK)SZ)r   r   )Qr   )r   r   )MN)Lr   )r   r   )PR)r   J)2r   )5r   )8r   )1r   )r   r   )0r   )r   r   )r   r   )r   r   FTc                 "    || _         || _        d S r   )long_stringsr#   )r$   r   r#   s      r%   r&   zStrCmp95.__init__#  s    ( r'   c                     dS rr   r*   rs   s     r%   rt   zStrCmp95.maximum'  ru   r'   c                 <    dt          |           cxk     odk     nc S )Nr   [   )ord)chars    r%   	_in_rangezStrCmp95._in_range*  s*    3t99!!!!r!!!!!r'   c                    |                                                                 }|                                                                 }|                     ||          }||S t          |          }t          |          }t	          t
                    }| j        D ]\  }}d|||f<   d|||f<   ||k    r|}	|}
n|}	|}
dg|	z  }dg|	z  }t          d|	dz  dz
            }	d}|dz
  }t          |          D ]j\  }}t          ||	z
  d          }t          ||	z   |          }t          ||dz             D ]+}||         dk    r||         |k    rd||<   d||<   |dz  } n,k|dk    rdS dx}}t          |          D ]E\  }}||         st          ||          D ]}||         dk    r|dz   } n|||         k    r|dz  }F|dz  }d}|
|k    rt          |          D ]}||         dk    r|                     ||                   s+t          |          D ]\}||         dk    r|                     ||                   s+||         ||         f|vr>||||         ||         f         z  }d||<    |dz  |z   }||z  ||z  z   }|||z
  |z  z  }|dz  }|dk    r|S t          |
d	          }d}t          ||          D ]0\  }}||k    r n$||k    r n|                                r n|dz  }1|r||d
z  d|z
  z  z  }| j        s|S |
d	k    r|S ||dz   k    sd|z  |
|z   k     r|S |d                                         r|S ||z
  dz
  ||z   |dz  z
  dz   z  }|d|z
  |z  z  }|S )Nry   r   r_   r   rx   g      $@g      @rz   r{   rv   r|   )stripupperr/   rA   r   ra   sp_mxr}   rb   rB   rK   r   r0   isdigitr   )r$   rC   rD   r3   r   r   adjwtr   r   r   minvs1_flags2_flagnum_comyl1rd   r   lowlimhilimre   r   n_transn_siminum_simr   r   ress                              r%   r5   zStrCmp95.__call__.  s   XXZZXXZZ""2r**MRRC   j 	 	FBE"b&ME"b&MMF??!LDD!LD #$#$1la/!344 qjmm 	 	FAs\)1--FL(#..E6519--  1:??r!u||!"GAJ!"GAJqLGE a<<3 Gmm 	 	FAs1: 1f%%  1:??AAE # be||1Q, '>>6]]  1:??~~be,, v 	 	AqzQ >>"Q%00 ! 1r!u~U22 eBqE2a5L11F!"GAJ4-') 6!Gf$447W$//# S==M aLLB 	 	HCAvvczz{{}} FAA 	/a#gv..F   	M199Ma!eq7{TAX55Ma5==?? 	M{Q6F?QU#:Q#>?3<3&&r'   N)FT)
r6   r7   r8   r9   r   r&   rt   staticmethodr   r5   r*   r'   r%   r   r     sw         E! ! ! !   " " \"x x x x xr'   r   c                   &    e Zd ZdZd
dZd Zd Zd	S )r	   a*  
    Compute the Hamming distance between the two or more sequences.
    The Hamming distance is the number of differing items in ordered sequences.

    http://www.sial.iias.spb.su/files/386-386-1-PB.pdf
    https://github.com/Yomguithereal/talisman/blob/master/src/metrics/distance/mlipns.js
          ?r_   r   Tc                 >    || _         || _        || _        || _        d S r   )r   	thresholdmaxmismatchesr#   )r$   r  r  r   r#   s        r%   r&   zMLIPNS.__init__  s#    	"* r'   c                     dS rr   r*   rs   s     r%   rt   zMLIPNS.maximum  ru   r'   c                 b    | j         | } | j        | }||S d} t                      | }t          t	          t
          |                    }t          |          rN|| j        k    rC|sdS d||z
  |z  z
  | j        k    rdS |dz  }|dz  }|dz  }t          |          r|| j        k    C|sdS dS )Nr   r   )	r.   r/   r   r}   r   rA   allr  r  )r$   r2   r3   
mismatcheshammaxlens         r%   r5   zMLIPNS.__call__  s    'D'3	""I.M
gii#Si(()))nn 	t/A!A!A qFSLF**dn<<q!OJ1HCaKF )nn 	t/A!A!A  	1qr'   N)r  r_   r   Tr   r*   r'   r%   r	   r	     sP         ! ! ! !      r'   r	   )!collectionsr   	itertoolsr   baser   _Baser   _BaseSimilarityrI   r   __all__r   r
   r   r   r   r   r   r   r   r	   r   r   dameraur   r   r   r   r   r   r   r   r*   r'   r%   <module>r     s   # # # # # # ! ! ! ! ! ! C B B B B B B BLLLL   EEE
 
 
I I I I Ie I I I0A$ A$ A$ A$ A$% A$ A$ A$Hb) b) b) b) b) b) b) b)Ja a a a a/ a a aH
 
 
 
 
; 
 
 
OF OF OF OF OFo OF OF OFd,F ,F ,F ,F ,FO ,F ,F ,F^F: F: F: F: F:O F: F: F:RQ Q Q Q Q Q Q Qh& & & & &_ & & &R '))kmm 2 2 4 4 4
tvv{}}"?$$ 8::	s    %%