a
    diB                     @   s  d dl Z d dlmZmZ d dlmZmZmZmZm	Z	 dZ
dZedZeG dd deeZG d	d
 d
Ze	ee eee  f e	eee f eeee  ee f dddZee ee edddZeedf eedf dddZeedf eeeef ee ee f dddZdS )    N)Enumunique)DictListSequenceTupleUnion   i'  g 7yACc                   @   s$   e Zd ZdZdZdZdZdZdZdS )_EditOperationsz1Enumerations for the Levenhstein edit operations.insertdelete
substituteZnothingZ	undefinedN)	__name__
__module____qualname____doc__	OP_INSERT	OP_DELETEOP_SUBSTITUTE
OP_NOTHINGOP_UNDEFINED r   r   l/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/text/helper.pyr
   +   s   r
   c                
   @   sN  e Zd ZdZdee eeeddddZee eeee	df f dd	d
Z
ee eeeeee	f   eeeeeee	f   ee	df f dddZeeeeee	f   ee	df dddZee eeeee	f   ddddZee eeeeeee	f   f dddZeeeee	f  dddZeeeee	f  dddZdS )_LevenshteinEditDistancea-  A convenience class for calculating the Levenshtein edit distance.

    Class will cache some intermediate values to hasten the calculation. The implementation follows the implemenation
    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

       N)reference_tokens	op_insert	op_deleteop_substitutereturnc                 C   s>   || _ t|| _i | _d| _|| _|| _|| _d| _t	| _
d S )Nr   )r   lenreference_lencache
cache_sizer   r   r   
op_nothing_INT_INFINITYop_undefined)selfr   r   r   r   r   r   r   __init__E   s    
z!_LevenshteinEditDistance.__init__.)prediction_tokensr   c                 C   s6   |  |\}}| |||\}}}| || ||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_positionZcached_edit_distanceZedit_distance_intedit_distancetracer   r   r   __call__T   s    
z!_LevenshteinEditDistance.__call__)r)   prediction_startr"   r   c                    s  t |} fddt|| D }|| }|r8 j| nd}|d tkrZt|d t nt}t|d |d D ]T}	t|	| }
td|
| }|	|kr jd nt jd |
| }t||D ] }|dkr||	d  | d  j	 t
jf||	 |< q||	d   j|d  kr$ j}t
j}n j}t
j}||	d  |d  d | |f||	d  | d  j	 t
jf||	 |d  d  j t
jff}|D ]0\}}||	 | d |kr||f||	 |< qqqp ||}|d d d |t |d |fS )	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

        c                    s   g | ]}t   jqS r   )list_get_empty_rowr!   .0_r'   r   r   
<listcomp>|   s   zG_LevenshteinEditDistance._levenshtein_edit_distance.<locals>.<listcomp>g      ?   r   r   N)r    ranger!   _BEAM_WIDTHmathceilfloormaxminr   r
   r   r   r$   r   r   r   r   r   
_get_trace)r'   r)   r1   r"   prediction_lenZ
empty_rowsr.   Zlength_ratioZ
beam_widthiZpseudo_diagZmin_jZmax_jjZcost_substituteZoperation_substitute
operationsZoperation_costZoperation_namer/   r   r7   r   r+   i   s>    

"$z3_LevenshteinEditDistance._levenshtein_edit_distance)rC   r.   r   c                 C   s   d}|}| j }|dks|dkr|| | d }|g|R }|tjtjfv r\|d8 }|d8 }q|tjkrp|d8 }q|tjkr|d8 }qtd|q|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'   rC   r.   r/   rD   rE   	operationr   r   r   rB      s    




z#_LevenshteinEditDistance._get_trace)r)   r.   r   c           	      C   s   | j tkrdS | j}t|t| }t|D ]}|||  d }q,t||d |D ]>\}}||vri t|f||< |  j d7  _ || }|d }qTdS )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)   r.   nodeZskip_numrD   wordrowvaluer   r   r   r,      s    
z#_LevenshteinEditDistance._add_cachec                 C   sV   | j }d}| | jg}|D ]0}||v rH|d7 }|| \}}|| q qNq||fS )a+  Find the already calculated rows of the Levenshtein edit distance matric.

        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)   rM   r-   r.   rN   rO   r   r   r   r*      s    z$_LevenshteinEditDistance._find_cache)lengthr   c                 C   s   t | jtjfg|d  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'   rS   r   r   r   r3     s    
z'_LevenshteinEditDistance._get_empty_rowc                    s    fddt |d D S )a0  First row corresponds to insertion operations of the reference, so we do 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.

        c                    s   g | ]}| j  tjfqS r   )r   r
   r   )r5   rD   r7   r   r   r8   &      z=_LevenshteinEditDistance._get_initial_row.<locals>.<listcomp>r   )r;   rU   r   r7   r   rQ     s    
z)_LevenshteinEditDistance._get_initial_row)r   r   r   )r   r   r   r   r   strrT   r(   r   r
   r0   r+   rB   r,   r*   r3   rQ   r   r   r   r   r   6   s&    $$E
&&!,r   )
ref_corpushypothesis_corpusr   c                 C   s   t |tr|g}tdd | D rBt|dkr4| gndd | D } |rtdd | D rt| t|krtdt|  dt| | |fS )	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                 s   s   | ]}t |tV  qd S N)
isinstancerW   r5   refr   r   r   	<genexpr>@  rV   z#_validate_inputs.<locals>.<genexpr>r   c                 S   s   g | ]
}|gqS r   r   r\   r   r   r   r8   A  rV   z$_validate_inputs.<locals>.<listcomp>c                 s   s   | ]
}|V  qd S rZ   r   r\   r   r   r   r^   C  rV   zCorpus has different size z != )r[   rW   allr    rH   )rX   rY   r   r   r   _validate_inputs)  s    
 &r`   )r)   r   r   c                    s   fddt t| d D }t t| d D ]}||| d< q.t t d D ]}||d |< qPt dt| d D ]}t dt d D ]z}| |d   |d  kr||d  |d  || |< qt||d  | || |d  ||d  |d  d || |< qqt|d d S )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

    c                    s   g | ]}d gt  d  qS )r   r   )r    r4   r   r   r   r8   S  rV   z"_edit_distance.<locals>.<listcomp>r   r   r:   )r;   r    rA   )r)   r   ZdprD   rE   r   ra   r   _edit_distanceI  s    
Drb   .)r/   r   c                    sF   t jt jt jt ji t tt t f t dddt fd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.

    )rI   _flip_operationsr   c                 S   s   | |v r| | S | S rZ   )get)rI   rc   r   r   r   _replace_operation_or_retains  s    
z1_flip_trace.<locals>._replace_operation_or_retainc                 3   s   | ]}| V  qd S rZ   r   )r5   rI   rc   re   r   r   r^   z  rV   z_flip_trace.<locals>.<genexpr>)r
   r   r   r   rL   )r/   r   rf   r   _flip_tracea  s    rg   c                 C   s   d }}g }g }i }| D ]}|t jkrT|d7 }|d7 }|||< |d |d q|t jkr|d7 }|d7 }|||< |d |d q|t jkr|d7 }|d q|t jkr|d7 }|||< |d qtd|dq|||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   rG   .)r
   r   rR   r   r   r   rH   )r/   Zreference_positionZhypothesis_positionZreference_errorsZhypothesis_errorsZ
alignmentsrI   r   r   r   _trace_to_alignment}  s4    





ri   )r=   enumr   r   typingr   r   r   r   r   r<   rJ   rT   r%   rW   r
   r   r`   rb   rg   ri   r   r   r   r   <module>   s    
 u  