o
    .wi                     @   s   d dl mZmZmZmZ d dlZd dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZmZ d dlmZmZ es=d	gZesCd
d	gZG dd
 d
eZdS )    )AnyOptionalSequenceUnionN)Tensor)multiclass_confusion_matrix)_cluster_accuracy_compute)Metric)_MATPLOTLIB_AVAILABLE"_TORCH_LINEAR_ASSIGNMENT_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEClusterAccuracy.plotClusterAccuracyc                       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
< eed< dededdf fddZdededdfddZdefddZddeeee df dee defddZ  ZS )r   a  Compute `Cluster Accuracy`_ between predicted and target clusters.

    .. math::

        \text{Cluster Accuracy} = \max_g \frac{1}{N} \sum_{n=1}^N \mathbb{1}_{g(p_n) = t_n}

    Where :math:`g` is a function that maps predicted clusters :math:`p` to target clusters :math:`t`, :math:`N` is the
    number of samples, :math:`p_n` is the predicted cluster for sample :math:`n`, :math:`t_n` is the target cluster for
    sample :math:`n`, and :math:`\mathbb{1}` is the indicator function. The function :math:`g` is determined by solving
    the linear sum assignment problem.

    This clustering metric is an extrinsic measure, because it requires ground truth clustering labels, which may not
    be available in practice since clustering in generally is used for unsupervised learning.

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

    - ``preds`` (:class:`~torch.Tensor`): single integer tensor with shape ``(N,)`` with predicted cluster labels
    - ``target`` (:class:`~torch.Tensor`): single integer tensor with shape ``(N,)`` with ground truth cluster labels

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

    - ``acc_score`` (:class:`~torch.Tensor`): A tensor with the Cluster Accuracy score

    Args:
        num_classes: number of classes
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        RuntimeError:
            If ``torch_linear_assignment`` is not installed. To install, run ``pip install torchmetrics[clustering]``.
        ValueError
            If ``num_classes`` is not a positive integer

    Example::
        >>> import torch
        >>> from torchmetrics.clustering import ClusterAccuracy
        >>> preds = torch.tensor([0, 0, 1, 1])
        >>> target = torch.tensor([1, 1, 0, 0])
        >>> metric = ClusterAccuracy(num_classes=2)
        >>> metric(preds, target)
        tensor(1.)

    Fis_differentiableThigher_is_betterfull_state_updateg        plot_lower_boundg      ?plot_upper_boundconfmatnum_classeskwargsreturnNc                    sb   t  jdi | tstdt|tr|dkrtd| jdtj	||ftj
ddd || _d S )	NzaMissing `torch_linear_assignment`. Please install it with `pip install torchmetrics[clustering]`.r   z3Argument `num_classes` should be a positive integerr   )dtypesum)defaultdist_reduce_fx )super__init__r   RuntimeError
isinstanceint
ValueError	add_statetorchzerosint64r   )selfr   r   	__class__r   e/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/clustering/cluster_accuracy.pyr   W   s   
zClusterAccuracy.__init__predstargetc                 C   s   |  j t||| jd7  _ dS )zAUpdate the confusion matrix with the new predictions and targets.)r   N)r   r   r   )r(   r,   r-   r   r   r+   updatee   s   zClusterAccuracy.updatec                 C   s
   t | jS )z!Computes the clustering accuracy.)r   r   )r(   r   r   r+   computei   s   
zClusterAccuracy.computevalaxc                 C   s   |  ||S )av  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
            >>> import torch
            >>> from torchmetrics.clustering import ClusterAccuracy
            >>> metric = ClusterAccuracy(num_classes=4)
            >>> metric.update(torch.randint(0, 4, (10,)), torch.randint(0, 4, (10,)))
            >>> fig_, ax_ = metric.plot(metric.compute())

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.clustering import ClusterAccuracy
            >>> metric = ClusterAccuracy(num_classes=4)
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(torch.randint(0, 4, (10,)), torch.randint(0, 4, (10,))))
            >>> fig_, ax_ = metric.plot(values)

        )_plot)r(   r0   r1   r   r   r+   plotm   s   'r   )NN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   floatr   r   r"   r   r   r.   r/   r   r   r   r   r   r3   __classcell__r   r   r)   r+   r   #   s   
 ,2)typingr   r   r   r   r%   r   &torchmetrics.functional.classificationr   3torchmetrics.functional.clustering.cluster_accuracyr   torchmetrics.metricr	   torchmetrics.utilities.importsr
   r   torchmetrics.utilities.plotr   r   __doctest_skip__r   r   r   r   r+   <module>   s   