o
    yi"                  	   @   s   d dl Z d dlmZmZ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 d dlmZmZmZ dZdZdZ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 ZG d	d
 d
eZdS )    N)AnyDictIteratorListOptionalSequenceTupleUnion)Tensortensor)Metric)_chrf_score_compute_chrf_score_update_prepare_n_grams_dicts)charword)predstargetmatching)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_gramsc                       s@  e Zd ZU dZdZeed< dZeed< dZeed< dZ	e
ee  ed< 			
				d*dededededededef fddZdee deee  ddfddZdeeeeef f fddZdefddZdeddfdd Zed!ed"edefd#d$Zed!ed"ed%edefd&d'Zdeeeeef ef  fd(d)Z  ZS )+	CHRFScorea  Calculate `chrf score`_ of machine translated text with one or more references.

    This implementation supports both ChrF score computation introduced in `chrF score`_ 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.

    As input to ``forward`` and ``update`` the metric accepts the following input:

    - ``preds`` (:class:`~Sequence`): An iterable of hypothesis corpus
    - ``target`` (:class:`~Sequence`): An iterable of iterables of reference corpus

    As output of ``forward`` and ``compute`` the metric returns the following output:

    - ``chrf`` (:class:`~torch.Tensor`): If `return_sentence_level_score=True` return a list of sentence-level
      chrF/chrF++ scores, else return a corpus-level chrF/chrF++ score

    Args:
        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: 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 keep whitespaces during n-gram extraction.
        return_sentence_level_score: An indication whether a sentence-level chrF/chrF++ score to be returned.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    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 import CHRFScore
        >>> preds = ['the cat is on the mat']
        >>> target = [['there is a cat on the mat', 'a cat is on the mat']]
        >>> chrf = CHRFScore()
        >>> chrf(preds, target)
        tensor(0.8640)
    Fis_differentiableThigher_is_betterfull_state_updateNsentence_chrf_score             @n_char_ordern_word_orderbeta	lowercase
whitespacereturn_sentence_level_scorekwargsc                    s   t  jdi | t|tr|dk rtd|| _t|tr"|dk r&td|| _|dk r1td|| _|| _|| _	|| _
t|| | _|  D ]!\\}}	}
td|	d D ]}| |
||}| j|tddd qUqH| j
rw| jd	g d
d d S d S )N   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.g        sum)dist_reduce_fxr   cat )super__init__
isinstanceint
ValueErrorr#   r$   r%   r&   r'   r(   floatn_order_get_text_n_gram_iteratorrange_get_state_name	add_stater   )selfr#   r$   r%   r&   r'   r(   r)   n_gram_leveln_gram_ordertextn
state_name	__class__r.   J/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/text/chrf.pyr0   `   s,   
zCHRFScore.__init__r   r   returnc                 C   sx   t ||g|  | j| j| j| j| j| j| jr | j	ndR  }| 
|dd  | j	dur:|d | _	dS dS )z*Update state with predictions and targets.N)r   _convert_states_to_dictsr#   r$   r5   r%   r&   r'   r(   r   _update_states_from_dicts)r:   r   r   n_grams_dicts_tupler.   r.   rB   update   s0   	

zCHRFScore.updatec                 C   sR   | j durtg |  | j| jR  t| j fS tg |  | j| jR  S )zCalculate chrF/chrF++ score.N)r   r   rE   r5   r%   torchr-   r:   r.   r.   rB   compute   s
   

zCHRFScore.computec                 C   s   dd t tt| j| jD }|  D ]&\\}}}td|d D ]}| ||}| |||}t	| ||| |< q qt
| S )z_Convert global metric states to the n-gram dictionaries to be passed in ``_chrf_score_update``.c                 S      i | ]\}}||qS r.   r.   .0namen_gram_dictr.   r.   rB   
<dictcomp>   s    z6CHRFScore._convert_states_to_dicts.<locals>.<dictcomp>r*   )zip_DICT_STATES_NAMESr   r#   r$   r6   r7   _get_dict_namer8   getattrtuplevalues)r:   n_grams_dictsr;   r<   r=   r>   	dict_namer?   r.   r.   rB   rE      s   z"CHRFScore._convert_states_to_dictsrG   c           	      C   sp   dd t t|D }|  D ]'\\}}}td|d D ]}| ||}| |||}t| ||| |  qqdS )z]Update global metric states based on the n-gram dictionaries calculated on the current batch.c                 S   rL   r.   r.   rM   r.   r.   rB   rQ      s    z7CHRFScore._update_states_from_dicts.<locals>.<dictcomp>r*   N)rR   rS   r6   r7   rT   r8   setattr)	r:   rG   rX   r;   r<   r=   r>   rY   r?   r.   r.   rB   rF      s   z#CHRFScore._update_states_from_dictsr=   r;   c                 C   s   d|  d| dS )z*Return a dictionary name w.r.t input args.total___n_gramsr.   )r=   r;   r.   r.   rB   rT      s   zCHRFScore._get_dict_namer>   c                 C   s   d|  d| d| dS )z,Return a metric state name w.r.t input args.r[   r\   _gramsr.   )r=   r;   r>   r.   r.   rB   r8      s   zCHRFScore._get_state_namec                 C   s   t tt| j| jgtS )zKGet iterator over char/word and reference/hypothesis/matching n-gram level.)	itertoolsproductrR   _N_GRAM_LEVELSr#   r$   _TEXT_LEVELSrJ   r.   r.   rB   r6      s   z#CHRFScore._get_text_n_gram_iterator)r    r!   r"   FFF) __name__
__module____qualname____doc__r   bool__annotations__r   r   r   r   r   r
   r2   r4   r   r0   r   strrH   r	   r   rK   _DICT_STATES_TYPESrE   rF   staticmethodrT   r8   r   r6   __classcell__r.   r.   r@   rB   r   .   sH   
 +"$	
*r   )r_   typingr   r   r   r   r   r   r   r	   rI   r
   r   torchmetricsr   !torchmetrics.functional.text.chrfr   r   r   ra   rb   rS   r2   rj   r   r.   r.   r.   rB   <module>   s   (	>