
    ilB              	       ^   d dl Z d dlmZ d dlmZmZ d dlmZ dZdZ	 e
d      Ze G d d	ee             Z G d
 d      Zdeee   eee      f   deeee   f   deeee      ee   f   fdZdee   dee   de
fdZdeedf   deedf   fdZdeedf   deee
e
f   ee
   ee
   f   fdZy)    N)Sequence)Enumunique)Union   i'  g 7yACc                   $    e Zd ZdZdZdZdZdZdZy)_EditOperationsz1Enumerations for the Levenhstein edit operations.insertdelete
substitutenothing	undefinedN)	__name__
__module____qualname____doc__	OP_INSERT	OP_DELETEOP_SUBSTITUTE
OP_NOTHINGOP_UNDEFINED     x/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/functional/text/helper.pyr	   r	   ,   s    ;II MJLr   r	   c                      e Zd ZdZ	 ddee   dedededdf
dZd	ee   deeee	d
f   f   fdZ
d	ee   dedeeeee	f         deeeeeee	f         ee	d
f   f   fdZdedeeeee	f         dee	d
f   fdZd	ee   deeeee	f         ddfdZd	ee   deeeeeee	f         f   fdZdedeeee	f      fdZdedeeee	f      fdZy)_LevenshteinEditDistancea.  A convenience class for calculating the Levenshtein edit distance.

    Class will cache some intermediate values to hasten the calculation. The implementation follows the implementation
    from https://github.com/mjpost/sacrebleu/blob/master/sacrebleu/metrics/lib_ter.py,
    where the most of this implementation is adapted and copied from.

    Args:
        reference_tokens: list of reference tokens
        op_insert: cost of insertion operation
        op_delete: cost of deletion operation
        op_substitute: cost of substitution operation

    reference_tokens	op_insert	op_deleteop_substitutereturnNc                     || _         t        |      | _        i | _        d| _        || _        || _        || _        d| _        t        | _
        y )Nr   )r   lenreference_lencache
cache_sizer   r   r    
op_nothing_INT_INFINITYop_undefined)selfr   r   r   r    s        r   __init__z!_LevenshteinEditDistance.__init__F   sM     !1 !1213
""*)r   prediction_tokens.c                     | j                  |      \  }}| j                  |||      \  }}}| j                  ||       ||fS )a(  Calculate edit distance between self._words_ref and the hypothesis. Uses cache to skip some computations.

        Args:
            prediction_tokens: A tokenized predicted sentence.

        Return:
            A tuple of a calculated edit distance and a trace of executed operations.

        )_find_cache_levenshtein_edit_distance
_add_cache)r*   r,   start_positioncached_edit_distanceedit_distance_intedit_distancetraces          r   __call__z!_LevenshteinEditDistance.__call__U   sW     04/?/?@Q/R,,262Q2Q~/C3
/=% 	)=9 %''r   prediction_startr%   c                    t        |      }t        ||z
        D cg c]&  }t        | j                  | j                              ( }}||z   }|r| j                  |z  nd}|dz  t
        kD  rt        j                  |dz  t
        z         nt
        }	t        |dz   |dz         D ]  }
t        j                  |
|z        }t        d||	z
        }|
|k(  r| j                  dz   nt        | j                  dz   ||	z         }t        ||      D ]  }|dk(  r2||
dz
     |   d   | j                  z   t        j                  f||
   |<   ;||
dz
     | j                  |dz
     k(  r| j                  }t        j                   }n| j"                  }t        j$                  }||
dz
     |dz
     d   |z   |f||
dz
     |   d   | j                  z   t        j                  f||
   |dz
     d   | j&                  z   t        j(                  ff}|D ]  \  }}||
   |   d   |kD  s||f||
   |<       | j+                  ||      }|d   d   d   |t        |      d |fS c c}w )a  Dynamic programming algorithm to compute the Levenhstein edit distance.

        Args:
            prediction_tokens: A tokenized predicted sentence.
            prediction_start: An index where a predicted sentence to be considered from.
            cache: A cached Levenshtein edit distance.

        Returns:
            Edit distance between the predicted sentence and the reference sentence

        g      ?      r   N)r#   rangelist_get_empty_rowr$   _BEAM_WIDTHmathceilfloormaxminr   r	   r   r   r'   r   r    r   r   r   
_get_trace)r*   r,   r7   r%   prediction_len_
empty_rowsr4   length_ratio
beam_widthipseudo_diagmin_jmax_jjcost_substituteoperation_substitute
operationsoperation_costoperation_namer5   s                        r   r/   z3_LevenshteinEditDistance._levenshtein_edit_distancej   s   " ./ DIZjIjCk?
CkaD$$T%7%789Ck 	 ?
 BGAS>Ot))N:UX COQRBRU`B`TYY|a/+=>fq
 '!+^a-?@A**Q%56K;34E*+~*=""Q&3tGYGY\]G]_jmw_wCx  5%(6%a!e,Q/2T^^C'11+M!$Q'
 )Q/43H3HQ3OO*.///>/I/I,*.*<*</>/L/L, 'q1u-a!e4Q7/IK_`&q1u-a03dnnDoF_F_`&q)!a%03dnnDoF_F_`"J ;E6(+A.q1NB2@.2PM!,Q/ ;E1 ) AF >R $Q's5z|)DeKK_?
s   +IrF   r4   c                 N   d}|}| j                   }|dkD  s|dkD  r||   |   d   }|g|}|t        j                  t        j                  fv r|dz  }|dz  }n@|t        j                  k(  r|dz  }n'|t        j
                  k(  r|dz  }nt        d|      |dkD  r|dkD  r|S )a@  Get a trace of executed operations from the edit distance matrix.

        Args:
            prediction_len: A length of a tokenized predicted sentence.
            edit_distance:
                A matrix of the Levenshtedin edit distance. The element part of the matrix is a tuple of an edit
                operation cost and an edit operation itself.

        Return:
            A trace of executed operations returned as a tuple of `_EDIT_OPERATIONS` enumerates.

        Raises:
            ValueError:
                If an unknown operation has been applied.

        r   r   r:   Unknown operation )r$   r	   r   r   r   r   
ValueError)r*   rF   r4   r5   rK   rO   	operations          r   rE   z#_LevenshteinEditDistance._get_trace   s    & .0!eq1u%a(+A.I''E_::O<V<VWWQQo777Qo777Q #5i]!CDD !eq1u r   c                 <   | j                   t        k\  ry| j                  }t        |      t        |      z
  }t	        |      D ]  }|||      d   } t        ||d |      D ]8  \  }}||vr%i t        |      f||<   | xj                   dz  c_         ||   }|d   }: y)a,  Add newly computed rows to cache.

        Since edit distance is only calculated on the hypothesis suffix that was not in cache, the number of rows in
        `edit_distance` matrx may be shorter than hypothesis length. In that case we skip over these initial words.

        Args:
            prediction_tokens: A tokenized predicted sentence.
            edit_distance:
                A matrix of the Levenshtedin edit distance. The element part of the matrix is a tuple of an edit
                operation cost and an edit operation itself.

        Nr   r:   )r&   _MAX_CACHE_SIZEr%   r#   r<   ziptuple)	r*   r,   r4   nodeskip_numrK   wordrowvalues	            r   r0   z#_LevenshteinEditDistance._add_cache   s     ??o-zz ()C,>> xA)!,-a0D ! .xy9=IID#4 %*-T
1$JE8D Jr   c                     | j                   }d}| j                  | j                        g}|D ])  }||v r|dz  }||   \  }}|j                  |       & ||fS  ||fS )a+  Find the already calculated rows of the Levenshtein edit distance metric.

        Args:
            prediction_tokens: A tokenized predicted sentence.

        Return:
            A tuple of a start hypothesis position and `edit_distance` matrix.

            prediction_start: An index where a predicted sentence to be considered from.
            edit_distance:
                A matrix of the cached Levenshtedin edit distance. The element part of the matrix is a tuple of an edit
                operation cost and an edit operation itself.

        r   r:   )r%   _get_initial_rowr$   append)r*   r,   r]   r1   r4   r_   r`   s          r   r.   z$_LevenshteinEditDistance._find_cache   s}     zzBFBWBWX\XjXjBkAl%Dt|!# J	c$$S)},, & },,r   lengthc                 Z    t        | j                        t        j                  fg|dz   z  S )a  Precomputed empty matrix row for Levenhstein edit distance.

        Args:
            length: A length of a tokenized sentence.

        Return:
            A list of tuples containing infinite edit operation costs and yet undefined edit operations.

        r:   )intr)   r	   r   )r*   re   s     r   r>   z'_LevenshteinEditDistance._get_empty_row  s-     T&&')E)EFG6TU:VVr   c                 ~    t        |dz         D cg c]!  }|| j                  z  t        j                  f# c}S c c}w )a*  First row corresponds to insertion operations of the reference, so 1 edit operation per reference word.

        Args:
            length: A length of a tokenized sentence.

        Return:
            A list of tuples containing edit operation costs of insert and insert edit operations.

        r:   )r<   r   r	   r   )r*   re   rK   s      r   rc   z)_LevenshteinEditDistance._get_initial_row  s>     JOvXYzIZ[IZAT^^#_%>%>?IZ[[[s   &:)r:   r:   r:   )r   r   r   r   r=   strrg   r+   r\   r	   r6   r/   rE   r0   r.   r>   rc   r   r   r   r   r   7   s    ij* $S	*69*JM*be*	*($s) (c5Z]I]C^>^8_ (*BL9BL BL DsO3456	BL
 
sDeC$89:;U?TWCW=XX	YBLH$!$26tE#BV<W7X2Y$	#	$$LDI d4PUVY[jVjPkKlFm rv B-T#Y -5d4PUVY[jVjPkKlFmAm;n -8
WS 
WT%_8L2M-N 
W
\s 
\tE#:N4O/P 
\r   r   
ref_corpushypothesis_corpusr!   c                 >   t        |t              r|g}t        d | D              r"t        |      dk(  r| gn| D cg c]  }|g c}} |rLt        d | D              r:t        |       t        |      k7  r#t	        dt        |        dt        |             | |fS c c}w )a  Check and update (if needed) the format of reference and hypothesis corpora for various text evaluation metrics.

    Args:
        ref_corpus: An iterable of iterables of reference corpus.
        hypothesis_corpus: An iterable of hypothesis corpus.

    Return:
        ref_corpus: An iterable of iterables of reference corpus.
        hypothesis_corpus: An iterable of hypothesis corpus.

    Raises:
        ValueError:
            If length of `ref_corpus` and `hypothesis_corpus` differs.

    c              3   <   K   | ]  }t        |t                y wN)
isinstanceri   .0refs     r   	<genexpr>z#_validate_inputs.<locals>.<genexpr>A  s     
6:C:c3:s   r:   c              3       K   | ]  }|  y wrn   r   rp   s     r   rs   z#_validate_inputs.<locals>.<genexpr>D  s      ;

s   zCorpus has different size z != )ro   ri   allr#   rW   )rj   rk   rr   s      r   _validate_inputsrv   *  s    & #S)./ 
6:
66%():%;q%@j\XbFcXbQTuXbFc
S ;
 ;;JSVWhSi@i5c*o5Fd3O`KaJbcdd((( Gds   
Br,   r   c           	      <   t        t        |       dz         D cg c]  }dgt        |      dz   z   }}t        t        |       dz         D ]
  }|||   d<    t        t        |      dz         D ]
  }||d   |<    t        dt        |       dz         D ]y  }t        dt        |      dz         D ]\  }| |dz
     ||dz
     k(  r||dz
     |dz
     ||   |<   )t        ||dz
     |   ||   |dz
     ||dz
     |dz
           dz   ||   |<   ^ { |d   d   S c c}w )a  Dynamic programming algorithm to compute the edit distance.

    Args:
        prediction_tokens: A tokenized predicted sentence
        reference_tokens: A tokenized reference sentence
    Returns:
        Edit distance between the predicted sentence and the reference sentence

    r:   r   r;   )r<   r#   rD   )r,   r   rG   dprK   rO   s         r   _edit_distancery   J  sV    6;3?P;QTU;U5V	W5V1#%&*
+5VB	W3()A-.1a /3'(1,-1a .1c+,q01q#./!34A Q'+;AE+BBa!e9QU+1ar!a%y|RU1q5\2a!e9QU;KLqP1a	 5 2 b6": 
Xs   Dr5   .c                     t         j                  t         j                  t         j                  t         j                  idt         dt        t         t         f   dt         fdt	        fd| D              S )a  Flip the trace of edit operations.

    Instead of rewriting a->b, get a recipe for rewriting b->a. Simply flips insertions and deletions.

    Args:
        trace: A tuple of edit operations.

    Return:
        inverted_trace:
            A tuple of inverted edit operations.

    rX   _flip_operationsr!   c                 0    | |v r|j                  |       S | S rn   )get)rX   r{   s     r   _replace_operation_or_retainz1_flip_trace.<locals>._replace_operation_or_retaint  s$     ((#''	22r   c              3   0   K   | ]  } |        y wrn   r   )rq   rX   r{   r~   s     r   rs   z_flip_trace.<locals>.<genexpr>{  s     b\ay-i9IJ\as   )r	   r   r   dictr\   )r5   r{   r~   s    @@r   _flip_tracer   b  sk     	!!?#<#<!!?#<#<@
"6:?O;[6\	 b\abbbr   c                    dx}}g }g }i }| D ]  }|t         j                  k(  r2|dz  }|dz  }|||<   |j                  d       |j                  d       H|t         j                  k(  r2|dz  }|dz  }|||<   |j                  d       |j                  d       |t         j                  k(  r|dz  }|j                  d       |t         j
                  k(  r|dz  }|||<   |j                  d       t        d|d       |||fS )a  Transform trace of edit operations into an alignment of the sequences.

    Args:
        trace: A trace of edit operations as a tuple of `_EDIT_OPERATIONS` enumerates.

    Return:
        alignments: A dictionary mapping aligned positions between a reference and a hypothesis.
        reference_errors: A list of error positions in a reference.
        hypothesis_errors: A list of error positions in a hypothesis.

    Raises:
        ValueError:
            If an unknown operation is

    r;   r:   r   rV   .)r	   r   rd   r   r   r   rW   )r5   reference_positionhypothesis_positionreference_errorshypothesis_errors
alignmentsrX   s          r   _trace_to_alignmentr   ~  sB     021,"$#%!#J 	2221$!#-@J)*##A&$$Q'/7771$!#-@J)*##A&$$Q'/3331$$$Q'/333!#-@J)*##A&1)a@AA+ . '):::r   )r@   collections.abcr   enumr   r   typingr   r?   rZ   rg   r(   ri   r	   r   r\   rv   r=   ry   r   r   r   r   r   r   <module>r      s>  >  $    D	 c4  p\ p\f)hsmXhsm%<<=)S(3-/0) 8HSM"HSM12)@d3i 49 QT 0cu_c12 cu_c=Q7R c8-;u_c%9: -;uT#s(^UYZ]U^`deh`iEi?j -;r   