Ë
    ýÿæiú(  ã            	       ó  — 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sd	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e«      Zy)é    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_TYPEz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                   ó°  ‡ — 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<   	 	 	 	 	 	 d&dedede
dededededdfˆ fd„Zdee   deee      ddfd„Zdeeeeef   f   fd„Zdefd„Zdeddfd„Zedededefd„«       Zededed edefd!„«       Zdeeeeef   ef      fd"„Z 	 d'd#eeeee   f      d$ee!   de"fd%„Z#ˆ x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 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                 ó>  •— t        ‰| �  di |¤Ž t        |t        «      r|dk  rt	        d«      ‚|| _        t        |t        «      r|dk  rt	        d«      ‚|| _        |dk  rt	        d«      ‚|| _        || _        || _	        || _
        t        ||z   «      | _        | j                  «       D ]L  \  \  }}	}
t        d|	dz   «      D ]2  }| j                  |
||«      }| j!                  |t#        d«      d¬«       Œ4 ŒN | j                  r| j!                  d	g d
¬«       y y )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__s                €úk/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/text/chrf.pyr5   zCHRFScore.__init__j   s#  ø€ ô 	‰ÑÑ"˜6Ò"ä˜,¬Ô,°¸qÒ0@ÜÐlÓmÐmØ(ˆÔÜ˜,¬Ô,°¸qÒ0@ÜÐlÓmÐmØ(ˆÔØ�!Š8ÜÐMÓNÐNØˆŒ	Ø"ˆŒØ$ˆŒØ+FˆÔ(ä˜\¨LÑ8Ó9ˆŒð 37×2PÑ2PÖ2RÑ.Ñ(ˆ\˜<¨$Ü˜1˜l¨QÑ.Ö/�Ø!×1Ñ1°$¸ÀaÓH�
Ø—‘˜z¬6°#«;Àu�ÕMñ 0ð 3Sð
 ×+Ò+Ø�N‰NÐ0°"ÀUˆNÕKð ,ó    r   r   c                 óT  — t        ||g| j                  «       ¢| j                  ‘| j                  ‘| j                  ‘| j
                  ‘| j                  ‘| j                  ‘| j                  r| j                  nd‘­Ž }| j                  |dd «       | j                  �|d   | _	        yy)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_tuples       rF   ÚupdatezCHRFScore.updateŽ   sÎ   € ä0ØØð
ð ×*Ñ*Ó,ð
ð ×Ñð	
ð
 ×Ñð
ð �L‰Lð
ð �I‰Ið
ð �N‰Nð
ð �O‰Oð
ð )-×(HÒ(HˆD×$Ò$Èdò
Ðð 	×&Ñ&Ð':¸3¸BÐ'?Ô@Ø×#Ñ#Ð/Ø':¸2Ñ'>ˆDÕ$ð 0rG   c                 ó  — | j                   �Pt        g | j                  «       ¢| j                  ‘| j                  ‘­Ž t        j                  | j                   «      fS t        g | j                  «       ¢| j                  ‘| j                  ‘­Ž S )zCalculate chrF/chrF++ score.)r%   r   rJ   r:   r(   Útorchr2   ©r?   s    rF   ÚcomputezCHRFScore.compute    s�   € à×#Ñ#Ð/ä#Ð^ T×%BÑ%BÓ%DÐ^ÀdÇlÁlÐ^ÐTX×T]ÑT]Ò^Ü—	‘	˜$×2Ñ2Ó3ðð ô #Ð] D×$AÑ$AÓ$CÐ]ÀTÇ\Á\Ð]ÐSW×S\ÑS\Ò]Ð]rG   c           	      ón  — t        t        t        t        | j                  | j
                  «      «      «      }| j                  «       D ]S  \  \  }}}t        d|dz   «      D ]9  }| j                  ||«      }| j                  |||«      }t        | |«      ||   |<   Œ; ŒU t        |j                  «       «      S )z_Convert global metric states to the n-gram dictionaries to be passed in ``_chrf_score_update``.r/   )ÚdictÚzipÚ_DICT_STATES_NAMESr   r&   r'   r;   r<   Ú_get_dict_namer=   ÚgetattrÚtupleÚvalues)r?   Ún_grams_dictsr@   rA   rB   rC   Ú	dict_namerD   s           rF   rJ   z"CHRFScore._convert_states_to_dicts©   s³   € ä6:ÜÔ"Ô$:¸4×;LÑ;LÈd×N_ÑN_Ó$`Óaó7
ˆð 37×2PÑ2PÖ2RÑ.Ñ(ˆ\˜<¨$Ü˜1˜l¨QÑ.Ö/�Ø ×/Ñ/°°lÓC�	Ø!×1Ñ1°$¸ÀaÓH�
ä.5°d¸JÓ.G�˜iÑ(¨Ò+ñ	 0ð 3Sô �]×)Ñ)Ó+Ó,Ð,rG   rL   c                 ó  — t        t        t        |«      «      }| j                  «       D ]T  \  \  }}}t	        d|dz   «      D ]:  }| j                  ||«      }| j                  |||«      }t        | |||   |   «       Œ< ŒV y)z]Update global metric states based on the n-gram dictionaries calculated on the current batch.r/   N)rS   rT   rU   r;   r<   rV   r=   Úsetattr)	r?   rL   rZ   r@   rA   rB   rC   r[   rD   s	            rF   rK   z#CHRFScore._update_states_from_dicts¸   s…   € äœSÔ!3Ð5HÓIÓJˆØ26×2PÑ2PÖ2RÑ.Ñ(ˆ\˜<¨$Ü˜1˜l¨QÑ.Ö/�Ø ×/Ñ/°°lÓC�	Ø!×1Ñ1°$¸ÀaÓH�
ä˜˜j¨-¸	Ñ*BÀ1Ñ*EÕFñ	 0ñ 3SrG   rB   r@   c                 ó   — d| › d|› d�S )z*Return a dictionary name w.r.t input args.Útotal_Ú_Ú_n_gramsr3   )rB   r@   s     rF   rV   zCHRFScore._get_dict_nameÂ   s   € ð ˜�v˜Q˜|˜n¨HÐ5Ð5rG   rC   c                 ó   — d| › d|› d|› d�S )z,Return a metric state name w.r.t input args.r_   r`   Ú_gramsr3   )rB   r@   rC   s      rF   r=   zCHRFScore._get_state_nameÇ   s   € ð ˜�v˜Q˜|˜n¨A¨a¨S°Ð7Ð7rG   c                 ó~   — t        j                  t        t        | j                  | j
                  g«      t        «      S )zKGet iterator over char/word and reference/hypothesis/matching n-gram level.)Ú	itertoolsÚproductrT   Ú_N_GRAM_LEVELSr&   r'   Ú_TEXT_LEVELSrP   s    rF   r;   z#CHRFScore._get_text_n_gram_iteratorÌ   s.   € ä× Ñ ¤¤^°d×6GÑ6GÈ×IZÑIZÐ5[Ó!\Ô^jÓkÐkrG   ÚvalÚaxc                 ó&   — | j                  ||«      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?   ri   rj   s      rF   ÚplotzCHRFScore.plotÐ   s   € ðT �z‰z˜#˜rÓ"Ð"rG   )é   é   g       @FFF)NN)%Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚboolÚ__annotations__r    r!   r#   r9   r$   r%   r   r   r	   r7   r   r5   r   ÚstrrM   r   rX   rQ   Ú_DICT_STATES_TYPESrJ   rK   ÚstaticmethodrV   r=   r   r;   r   r   rm   Ú__classcell__)rE   s   @rF   r   r   5   sð  ø… ñ*ðX $Ð�tÓ#Ø!Ð�dÓ!Ø"Ð�tÓ"Ø!Ð�eÓ!Ø!Ð�eÓ!à26Ð˜ $ v¡,Ñ/Ó6ð ØØØØ Ø,1ñ"Làð"Lð ð"Lð ð	"Lð
 ð"Lð ð"Lð &*ð"Lð ð"Lð 
õ"LðH?˜H S™Mð ?°8¸HÀS¹MÑ3Jð ?Ètó ?ð$^˜˜v u¨V°V¨^Ñ'<Ð<Ñ=ó ^ð-Ð*<ó -ðGÐ=Oð GÐTXó Gð ð6˜Sð 6°ð 6¸ò 6ó ð6ð ð8˜cð 8°ð 8¸ð 8Àò 8ó ð8ðl¨8°E¸%ÀÀSÀ¹/È3Ð:NÑ4OÑ+Pó lð
 _cñ*#Ø˜E &¨(°6Ñ*:Ð":Ñ;Ñ<ð*#ØIQÐRZÑI[ð*#à	÷*#rG   r   ) re   Úcollections.abcr   r   Útypingr   r   r   r   rO   r	   r
   Útorchmetricsr   Ú!torchmetrics.functional.text.chrfr   r   r   Útorchmetrics.utilities.importsr   Útorchmetrics.utilities.plotr   r   Ú__doctest_skip__rg   rh   rU   rX   rS   r7   rw   r   r3   rG   rF   Ú<module>r�      s±   ðó( ß .ß -Ó -ã ß  å ß mÑ mÝ @ß @áØ(Ð)Ðð "€Ø.€ðÐ ð ØˆˆfˆÑ�t˜C ˜KÑ(¨$¨s°F¨{Ñ*;¸TÀ#ÀvÀ+Ñ=NÐPTÐUXÐZ`ÐU`ÑPaÐcgÐhkÐmsÐhsÑctÐtñÐ ô
E#�õ E#rG   