o
    .wi(                  	   @   s   d dl Z d dlmZmZ d dl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 dlmZ d dlmZmZ esGd	g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)IteratorSequence)AnyListOptionalUnion)Tensortensor)Metric)_chrf_score_compute_chrf_score_update_prepare_n_grams_dicts)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPECHRFScore.plot)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d< d	Ze
ed
< dZeee  ed< 						d2dedede
dededededd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 	d3d.eeeee f  d/ee! de"fd0d1Z#  Z$S )4	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 implementations 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-insensitivity.
        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.text 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_update        plot_lower_boundg      ?plot_upper_boundNsentence_chrf_score             @n_char_ordern_word_orderbeta	lowercase
whitespacereturn_sentence_level_scorekwargsreturnc                    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.r!   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__r4   S/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/text/chrf.pyr6   j   s,   
zCHRFScore.__init__r   r   c                 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)   r;   r*   r+   r,   r-   r$   _update_states_from_dicts)r@   r   r   n_grams_dicts_tupler4   r4   rH   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   rJ   r;   r*   torchr3   r@   r4   r4   rH   compute   s
   

zCHRFScore.computec                 C   sz   t ttt| j| j}|  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``.r0   )dictzip_DICT_STATES_NAMESr   r(   r)   r<   r=   _get_dict_namer>   getattrtuplevalues)r@   n_grams_dictsrA   rB   rC   rD   	dict_namerE   r4   r4   rH   rJ      s   z"CHRFScore._convert_states_to_dictsrL   c           	      C   sj   t tt|}|  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.r0   N)rQ   rR   rS   r<   r=   rT   r>   setattr)	r@   rL   rX   rA   rB   rC   rD   rY   rE   r4   r4   rH   rK      s   z#CHRFScore._update_states_from_dictsrC   rA   c                 C   s   d|  d| dS )z*Return a dictionary name w.r.t input args.total___n_gramsr4   )rC   rA   r4   r4   rH   rT      s   zCHRFScore._get_dict_namerD   c                 C   s   d|  d| d| dS )z,Return a metric state name w.r.t input args.r[   r\   _gramsr4   )rC   rA   rD   r4   r4   rH   r>      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_LEVELSrO   r4   r4   rH   r<      s   z#CHRFScore._get_text_n_gram_iteratorvalaxc                 C   s   |  ||S )a  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> from torchmetrics.text import CHRFScore
            >>> metric = CHRFScore()
            >>> preds = ['the cat is on the mat']
            >>> target = [['there is a cat on the mat', 'a cat is on the mat']]
            >>> metric.update(preds, target)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torchmetrics.text import CHRFScore
            >>> metric = CHRFScore()
            >>> preds = ['the cat is on the mat']
            >>> target = [['there is a cat on the mat', 'a cat is on the mat']]
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(preds, target))
            >>> fig_, ax_ = metric.plot(values)

        )_plot)r@   rc   rd   r4   r4   rH   plot   s   *r   )r%   r&   r'   FFF)NN)%__name__
__module____qualname____doc__r   bool__annotations__r   r    r"   r:   r#   r$   r   r   r   r8   r   r6   r   strrM   r   rV   rP   _DICT_STATES_TYPESrJ   rK   staticmethodrT   r>   r   r<   r   r   rf   __classcell__r4   r4   rF   rH   r   5   s`   
 ,	"$	
"r   ) r_   collections.abcr   r   typingr   r   r   r   rN   r   r	   torchmetricsr
   !torchmetrics.functional.text.chrfr   r   r   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   __doctest_skip__ra   rb   rS   rV   rQ   r8   rn   r   r4   r4   r4   rH   <module>   s$   	>