a
    de                     @   sH  d dl mZ d dlmZmZmZmZmZmZ d dl	Z	d dl	m
Z
mZ d dlmZ edZedZeeeeee
f eee
f eee
f eee
f eee
f eee
f f dd	d
Zeeee dddZeee dddZeee dddZee eeeeeedf e
f f dddZeeeeeeeeeeedf e
f f eeeeedf e
f f eee
f eee
f f dddZeeeeedf e
f f eeeeedf e
f f eee
f dddZeee
f eee
f eee
f ddd Zeee
f eee
f eee
f eee
f eee
f eee
f eee
d!	d"d#Zee eeeeedf e
f f eeeeedf e
f f eee
f eee
f eeeeeeee
eee
f eee
f eee
f eee
f f d$d%d&Zd4eeee f eee eee  f eee
f eee
f eee
f eee
f eee
f eee
f eeeeeeeee
  eeee
f eee
f eee
f eee
f eee
f eee
f eee
  f d'd(d)Zeee
f eee
f eee
f eee
f eee
f eee
f eee
d*	d+d,Z d5eeee f eeeee f  eeeeeeee
ee
e
f f d1	d2d3Z!dS )6    defaultdict)DictListOptionalSequenceTupleUnionN)Tensortensor)_validate_inputsgؗҜ<z !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)n_char_ordern_word_orderreturnc                 C   s|   dd t | D }dd t |D }dd t | D }dd t |D }dd t | D }dd t |D }||||||fS )ai  Prepare dictionaries with default zero values for total ref, hypothesis and matching chraracter and word n-grams.

    Args:
        n_char_order: A character n-gram order.
        n_word_order: A word n-gram order.

    Return:
        Dictionaries with default zero values for total reference, hypothesis and matching character and word
        n-grams.

    c                 S   s   i | ]}|d  t dqS            r   .0n r   j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/text/chrf.py
<dictcomp>@       z*_prepare_n_grams_dicts.<locals>.<dictcomp>c                 S   s   i | ]}|d  t dqS r   r   r   r   r   r   r   A   r   c                 S   s   i | ]}|d  t dqS r   r   r   r   r   r   r   B   r   c                 S   s   i | ]}|d  t dqS r   r   r   r   r   r   r   C   r   c                 S   s   i | ]}|d  t dqS r   r   r   r   r   r   r   D   r   c                 S   s   i | ]}|d  t dqS r   r   r   r   r   r   r   E   r   )range)r   r   total_preds_char_n_gramstotal_preds_word_n_gramstotal_target_char_n_gramstotal_target_word_n_gramstotal_matching_char_n_gramstotal_matching_word_n_gramsr   r   r   _prepare_n_grams_dicts0   s    r"   )sentence
whitespacer   c                 C   s    |rt | S t |  ddS )a   Split sentence into individual characters.

    Args:
        sentence: An input sentence to split.
        whitespace: An indication whether to keep whitespaces during character n-gram extraction.

    Return:
        A list of separated characters.

      )liststripreplace)r#   r$   r   r   r   _get_charactersQ   s    r*   )wordr   c                 C   sX   t | dkr| gS | d tv r2| dd | d gS | d tv rR| d | dd gS | gS )ay  Separates out punctuations from beginning and end of words for chrF.

    Adapted from https://github.com/m-popovic/chrF and
    https://github.com/mjpost/sacrebleu/blob/master/sacrebleu/metrics/chrf.py.

    Args:
        word: An input word to be separated from a punctuation if present.

    Return:
        A list of a single word or a separated word and punctuation.

    r   Nr   )len_PUNCTUATIONS)r+   r   r   r   _separate_word_and_punctiationa   s    r/   )r#   r   c                 C   s   t dd |   D g S )zSeparates out punctuations from beginning and end of words for chrF for all words in the sentence.

    Args:
        sentence: An input sentence to split

    Return:
        An aggregated list of separated words and punctuations.

    c                 s   s   | ]}t |V  qd S N)r/   )r   r+   r   r   r   	<genexpr>   r   z-_get_words_and_punctiation.<locals>.<genexpr>)sumr(   split)r#   r   r   r   _get_words_and_punctiationx   s    
r4   .)char_or_word_listn_gram_orderr   c                    sf   t dd }td|d D ]F fddtt  d D D ]}| |  td7  < qBq|S )zCalculate n-gram counts.

    Args:
        char_or_word_list: A list of characters of words
        n_gram_order: The largest number of n-gram.

    Return:
        A dictionary of dictionaries with a counts of given n-grams.

    c                   S   s   t dd S )Nc                   S   s   t dS Nr   r   r   r   r   r   <lambda>   r   z1_ngram_counts.<locals>.<lambda>.<locals>.<lambda>r   r   r   r   r   r8      r   z_ngram_counts.<locals>.<lambda>r   c                 3   s"   | ]}t  ||  V  qd S r0   )tuple)r   ir5   r   r   r   r1      r   z _ngram_counts.<locals>.<genexpr>)r   r   r-   r   )r5   r6   ZngramsZngramr   r;   r   _ngram_counts   s
    (r<   )r#   r   r   	lowercaser$   r   c                    s   t ttttttttt df tf f ttttt df tf f f d fdd}ttttt df tf f tttf ddd}|| |||\}}||}	||}
|||	|
fS )a  Get n-grams and total n-grams.

    Args:
        sentence: An input sentence
        n_char_order: A character n-gram order.
        n_word_order: A word n-gram order.
        lowercase: An indication whether to enable case-insensitivity.
        whitespace: An indication whether to keep whitespaces during character n-gram extraction.

    Return:
        char_n_grams_counts: A dictionary of dictionaries with sentence character n-grams.
        word_n_grams_counts: A dictionary of dictionaries with sentence word n-grams.
        total_char_n_grams: A dictionary containing a total number of sentence character n-grams.
        total_word_n_grams: A dictionary containing a total number of sentence word n-grams.

    .)r#   r   r   r=   r   c                    s2   |r|   } tt|  |}tt| |}||fS )z@Get a dictionary of dictionaries with a counts of given n-grams.)lowerr<   r*   r4   )r#   r   r   r=   char_n_grams_countsword_n_grams_countsr$   r   r   _char_and_word_ngrams_counts   s
    zJ_get_n_grams_counts_and_total_ngrams.<locals>._char_and_word_ngrams_counts)n_grams_countsr   c                 S   s2   t dd }| D ]}tt| |  ||< q|S )z.Get total sum of n-grams over n-grams w.r.t n.c                   S   s   t dS r7   r   r   r   r   r   r8      r   zQ_get_n_grams_counts_and_total_ngrams.<locals>._get_total_ngrams.<locals>.<lambda>)r   r   r2   values)rC   total_n_gramsr   r   r   r   _get_total_ngrams   s    z?_get_n_grams_counts_and_total_ngrams.<locals>._get_total_ngrams)strintboolr   r   r
   )r#   r   r   r=   r$   rB   rF   r?   r@   Ztotal_char_n_gramsZtotal_word_n_gramsr   rA   r   $_get_n_grams_counts_and_total_ngrams   s    :
0rJ   )hyp_n_grams_countsref_n_grams_countsr   c                    s@   t dd } D ]*tt fdd  D |< q|S )zGet a number of n-gram matches between reference and hypothesis n-grams.

    Args:
        hyp_n_grams_counts: n-grams counts for hypothesis
        ref_n_grams_counts: n-grams counts for reference

    Return:
        matching_n_grams

    c                   S   s   t dS r7   r   r   r   r   r   r8      r   z$_get_ngram_matches.<locals>.<lambda>c                 3   s*   | ]"}t  |   | V  qd S r0   )torchmin)r   Zn_gramrK   r   rL   r   r   r1      s   z%_get_ngram_matches.<locals>.<genexpr>)r   r   r2   )rK   rL   matching_n_gramsr   rO   r   _get_ngram_matches   s    
rQ   )rE   n_gramsr   c                 C   s"   |D ]}| |  || 7  < q| S )aB  Aggregate total n-grams to keep corpus-level statistics.

    Args:
        total_n_grams: A dictionary containing a total corpus-level number of n-grams.
        n_grams: A dictionary containing a sentence-level number of n-grams.

    Return:
        A dictionary containing a total corpus-level number of n-grams.

    r   )rE   rR   r   r   r   r   _sum_over_dicts   s    rS   )	matching_char_n_gramsmatching_word_n_gramshyp_char_n_gramshyp_word_n_gramsref_char_n_gramsref_word_n_gramsn_orderbetar   c                 C   sr   t ttf t ttf t ttf tt ttf ddd}|| |||}	|||||}
t|	 t|
  t| S )a  Calculate sentence-level chrF/chrF++ score.

    For given hypothesis and reference statistics (either sentence-level or corpus-level)
    the chrF/chrF++ score is returned.

    Args:
        matching_char_n_grams:
            A total number of matching character n-grams between the best matching reference and hypothesis.
        matching_word_n_grams:
            A total number of matching word n-grams between the best matching reference and hypothesis.
        hyp_char_n_grams: A total number of hypothesis character n-grams.
        hyp_word_n_grams: A total number of hypothesis word n-grams.
        ref_char_n_grams: A total number of reference character n-grams.
        ref_word_n_grams: A total number of reference word n-grams.
        n_order: A sum of character and word n-gram order.
        beta: A parameter determining an importance of recall w.r.t. precision. If `beta=1`, their importance is equal.

    Return:
        A chrF/chrF++ score. This function is universal both for sentence-level and corpus-level calucation.

    )rP   ref_n_gramshyp_n_gramsr[   r   c                    sZ   fddD fddD  fddD  fddD }|S )zGet n-gram level f-score.c                    s2   i | ]*}| | d kr&|  |  nt dqS r   r   r   r   )r]   rP   r   r   r     s   zA_calculate_fscore.<locals>._get_n_gram_fscore.<locals>.<dictcomp>c                    s2   i | ]*}|| d kr& | |  nt dqS r^   r   r   )rP   r\   r   r   r     s   c                    s.   i | ]&}|t  d  |  |  tqS )   )rM   max_EPS_SMOOTHINGr   )r[   	precisionrecallr   r   r     s   c                    s2   i | ]*}|d  d  |  |  |  qS )r   r_   r   r   )r[   denominatorrb   rc   r   r   r      s   r   )rP   r\   r]   r[   f_scorer   )r[   rd   r]   rP   rb   rc   r\   r   _get_n_gram_fscore  s    z-_calculate_fscore.<locals>._get_n_gram_fscore)r   rH   r
   floatr2   rD   r   )rT   rU   rV   rW   rX   rY   rZ   r[   rf   Zchar_n_gram_f_scoreZword_n_gram_f_scorer   r   r   _calculate_fscore   s    ! 
rh   )targetspred_char_n_grams_countspred_word_n_grams_countspred_char_n_gramspred_word_n_gramsr   r   rZ   r[   r=   r$   r   c              
   C   s   t d}tdd }tdd }tdd }tdd }| D ]b}t||||	|
\}}}}t||}t||}t||||||||}||kr<|}|}|}|}|}q<|||||fS )aS  Calculate the best sentence-level chrF/chrF++ score.

    For a given pre-processed hypothesis, all references are evaluated and score and statistics
    for the best matching reference is returned.

    Args:
        targets: An iterable of references.
        pred_char_n_grams_counts: A dictionary of dictionaries with hypothesis character n-grams.
        pred_word_n_grams_counts: A dictionary of dictionaries with hypothesis word n-grams.
        pred_char_n_grams: A total number of hypothesis character n-grams.
        pred_word_n_grams: A total number of hypothesis word n-grams.
        n_char_order: A character n-gram order.
        n_word_order: A word n-gram order.
        n_order: A sum of character and word n-gram order.
        beta: A parameter determining an importance of recall w.r.t. precision. If `beta=1`, their importance is equal.
        lowercase: An indication whether to enable case-insensitivity.
        whitespace: An indication whether to keep whitespaces during character n-gram extraction.

    Return:
        Return chrF/chrF++ score and statistics for the best matching hypothesis and reference.

        f_score: A sentence-level chrF/chrF++ score.
        matching_char_n_grams:
            A total number of matching character n-grams between the best matching reference and hypothesis.
        matching_word_n_grams:
            A total number of matching word n-grams between the best matching reference and hypothesis.
        target_char_n_grams: A total number of reference character n-grams.
        target_word_n_grams: A total number of reference word n-grams.

    r   c                   S   s   t dS r7   r   r   r   r   r   r8   X  r   z6_calculate_sentence_level_chrf_score.<locals>.<lambda>c                   S   s   t dS r7   r   r   r   r   r   r8   Y  r   c                   S   s   t dS r7   r   r   r   r   r   r8   Z  r   c                   S   s   t dS r7   r   r   r   r   r   r8   [  r   )r   r   rJ   rQ   rh   )ri   rj   rk   rl   rm   r   r   rZ   r[   r=   r$   Zbest_f_scoreZbest_matching_char_n_gramsZbest_matching_word_n_gramsZbest_target_char_n_gramsZbest_target_word_n_gramstargetZtarget_char_n_grams_countsZtarget_word_n_grams_countstarget_char_n_gramstarget_word_n_gramsrT   rU   re   r   r   r   $_calculate_sentence_level_chrf_score,  sH    +

rq   )predsrn   r   r   r   r   r    r!   r   r   rZ   r[   r=   r$   sentence_chrf_scorer   c                 C   s   t || \}} t| |D ]\}}t|||	||\}}}}t||}t||}t|||||||	|
|||\}}}}}|dur||d t||}t||}t||}t||}q|||||||fS )a  Update function for chrf score.

    Args:
        preds: An iterable of hypothesis corpus.
        target: An iterable of iterables of reference corpus.
        total_preds_char_n_grams: A dictionary containing a total number of hypothesis character n-grams.
        total_preds_word_n_grams: A dictionary containing a total number of hypothesis word n-grams.
        total_target_char_n_grams: A dictionary containing a total number of reference character n-grams.
        total_target_word_n_grams: A dictionary containing a total number of reference word n-grams.
        total_matching_char_n_grams:
            A dictionary containing a total number of matching character n-grams between references and hypotheses.
        total_matching_word_n_grams:
            A dictionary containing a total number of total matching word n-grams between references and hypotheses.
        n_char_order: A character n-gram order.
        n_word_order: A word n-gram order.
        n_order: Sum of character and word n-gram order.
        beta: A parameter determining an importance of recall w.r.t. precision. If `beta=1`, their importance is equal.
        lowercase: An indication whether to enable case-insensitivity.
        whitespace: An indication whether to keep whitespaces during character n-gram extraction.
        sentence_chrf_score: A list of sentence-level chrF/chrF++ scores.

    Return:
        total_target_char_n_grams: number of reference character n-grams.
        total_target_word_n_grams: number of reference word n-grams.
        total_preds_char_n_grams: number of hypothesis character n-grams.
        total_preds_word_n_grams: number of hypothesis word n-grams.
        total_matching_char_n_grams: number of matching character n-grams between references and hypotheses.
        total_matching_word_n_grams: number of total matching word n-grams between references and hypotheses.
        sentence_chrf_score: A list of sentence-level chrF/chrF++ scores.

    Raises:
        ValueError:
            If length of ``preds`` and ``target`` differs.

    Nr   )r   ziprJ   rS   rq   appendZ	unsqueeze)rr   rn   r   r   r   r   r    r!   r   r   rZ   r[   r=   r$   rs   Ztarget_corpuspredri   rj   rk   rl   rm   Zsentence_level_f_scorerT   rU   ro   rp   r   r   r   _chrf_score_update  sV    <




rw   )	r   r   r   r   r    r!   rZ   r[   r   c              	   C   s   t ||| |||||S )ak  Compute chrF/chrF++ score based on pre-computed target, prediction and matching character and word n-grams.

    Args:
        total_preds_char_n_grams: number of hypothesis character n-grams.
        total_preds_word_n_grams: number of hypothesis word n-grams.
        total_target_char_n_grams: number of reference character n-grams.
        total_target_word_n_grams: number of reference word n-grams.
        total_matching_char_n_grams: number of matching character n-grams between references and hypotheses.
        total_matching_word_n_grams: number of total matching word n-grams between references and hypotheses.
        n_order: A sum of character and word n-gram order.
        beta:
            A parameter determining an importance of recall w.r.t. precision. If `beta=1`, their importance is equal.

    Return:
        A corpus-level chrF/chrF++ score.

    )rh   )r   r   r   r   r    r!   rZ   r[   r   r   r   _chrf_score_compute  s    rx      r_          @F)	rr   rn   r   r   r[   r=   r$   return_sentence_level_scorer   c                 C   s   t |tr|dk rtdt |tr,|dk r4td|dk rDtdt|| }t||\}	}
}}}}|rng nd}t| ||	|
|||||||||||\}	}
}}}}}t|	|
||||||}|r|t|fS |S )u_  Calculate `chrF score`_  of machine translated text with one or more references.

    This implementation supports both chrF score computation introduced in [1] and chrF++ score introduced in
    `chrF++ score`_. This implementation follows the implmenetaions from https://github.com/m-popovic/chrF and
    https://github.com/mjpost/sacrebleu/blob/master/sacrebleu/metrics/chrf.py.

    Args:
        preds: An iterable of hypothesis corpus.
        target: An iterable of iterables of reference corpus.
        n_char_order:
            A character n-gram order. If `n_char_order=6`, the metrics refers to the official chrF/chrF++.
        n_word_order:
            A word n-gram order. If `n_word_order=2`, the metric refers to the official chrF++. If `n_word_order=0`, the
            metric is equivalent to the original chrF.
        beta:
            A parameter determining an importance of recall w.r.t. precision. If `beta=1`, their importance is equal.
        lowercase: An indication whether to enable case-insesitivity.
        whitespace: An indication whether to keep whitespaces during character n-gram extraction.
        return_sentence_level_score: An indication whether a sentence-level chrF/chrF++ score to be returned.

    Return:
        A corpus-level chrF/chrF++ score.
        (Optionally) A list of sentence-level chrF/chrF++ scores if `return_sentence_level_score=True`.

    Raises:
        ValueError:
            If ``n_char_order`` is not an integer greater than or equal to 1.
        ValueError:
            If ``n_word_order`` is not an integer greater than or equal to 0.
        ValueError:
            If ``beta`` is smaller than 0.

    Example:
        >>> from torchmetrics.functional.text import chrf_score
        >>> preds = ['the cat is on the mat']
        >>> target = [['there is a cat on the mat', 'a cat is on the mat']]
        >>> chrf_score(preds, target)
        tensor(0.8640)

    References:
        [1] chrF: character n-gram F-score for automatic MT evaluation by Maja Popović `chrF score`_

        [2] chrF++: words helping character n-grams by Maja Popović `chrF++ score`_

    r   zMExpected argument `n_char_order` to be an integer greater than or equal to 1.r   zMExpected argument `n_word_order` to be an integer greater than or equal to 0.z.Expected argument `beta` to be greater than 0.N)	
isinstancerH   
ValueErrorrg   r"   rw   rx   rM   cat)rr   rn   r   r   r[   r=   r$   r{   rZ   r   r   r   r   r    r!   rs   Zchrf_f_scorer   r   r   
chrf_score  sl    7	
r   )N)ry   r_   rz   FFF)"collectionsr   typingr   r   r   r   r   r	   rM   r
   r   Z#torchmetrics.functional.text.helperr   ra   setr.   rH   r"   rG   rI   r*   r/   r4   r<   rJ   rQ   rS   rg   rh   rq   rw   rx   r   r   r   r   r   <module>#   s    >!.


4
*





:

0e 













p





*      