o
    ¡¿¯i  ã                   @   sL   d dl mZ d dlmZ d dlZd dlmZ d dlmZ G dd„ deƒZ	dS )é    )Údefaultdict)ÚpermutationsN)Ú
AbsEnhLoss)ÚAbsLossWrapperc                       s6   e Zd Z			d	def‡ fdd„Zi fdd„Z‡  ZS )
Ú	PITSolverç      ð?TFÚ	criterionc                    s&   t ƒ  ¡  || _|| _|| _|| _dS )aG  Permutation Invariant Training Solver.

        Args:
            criterion (AbsEnhLoss): an instance of AbsEnhLoss
            weight (float): weight (between 0 and 1) of current loss
                for multi-task learning.
            independent_perm (bool):
                If True, PIT will be performed in forward to find the best permutation;
                If False, the permutation from the last LossWrapper output will be
                inherited.
                NOTE (wangyou): You should be careful about the ordering of loss
                    wrappers defined in the yaml config, if this argument is False.
            flexible_numspk (bool):
                If True, num_spk will be taken from inf to handle flexible numbers of
                speakers. This is because ref may include dummy data in this case.
        N)ÚsuperÚ__init__r   ÚweightÚindependent_permÚflexible_numspk)Úselfr   r   r   r   ©Ú	__class__© úX/home/ubuntu/.local/lib/python3.10/site-packages/espnet2/enh/loss/wrappers/pit_solver.pyr
      s
   

zPITSolver.__init__c                    s<  d|v r|d nd}ˆj s$tˆƒtˆ ƒksJ tˆƒtˆ ƒfƒ‚tˆƒ}ntˆ ƒ}ttƒ‰‡‡fdd„‰‡ ‡‡‡fdd„‰ˆjsC|du râˆd j}ttt|ƒƒƒ}tj	‡fdd	„|D ƒd
d}tj
|d
d\}	}
t tj||tjdd|
¡}ˆ ¡ D ]g\}}tj	|d
d}|j^}}}||t|ƒ ks˜J ||fƒ‚|j||| |g|¢R Ž  d¡}| ¡ dkrËdd	„ |D ƒ}|
j|
jd d
g|¢R Ž jddg|¢R Ž }n|
 d
¡}| d
|j|jd¡ d
¡ˆ|< qynt ‡ ‡‡‡fdd	„t|ƒD ƒ¡}	|	 ¡ }	ˆ ¡ D ]\}}tj	|d
d ¡ ˆ|< qû|	 ¡ ˆˆjj< |	 ¡ tˆƒd|ifS )aŠ  PITSolver forward.

        Args:
            ref (List[torch.Tensor]): [(batch, ...), ...] x n_spk
            inf (List[torch.Tensor]): [(batch, ...), ...]

        Returns:
            loss: (torch.Tensor): minimum loss with the best permutation
            stats: dict, for collecting training status
            others: dict, in this PIT solver, permutation order will be returned
        ÚpermNc                    s<   | |i |¤Ž}t ˆ jdi ƒ ¡ D ]\}}ˆ|  |¡ q|S )NÚstats)Úgetattrr   ÚitemsÚappend)ÚfuncÚargsÚkwargsÚretÚkÚv)r   r   r   r   Úpre_hook>   s   z#PITSolver.forward.<locals>.pre_hookc                    s(   t ‡ ‡‡‡fdd„t| ƒD ƒƒt| ƒ S )Nc                    s&   g | ]\}}ˆˆj ˆ| ˆ | ƒ‘qS r   )r   ©Ú.0ÚsÚt©Úinfr   Úrefr   r   r   Ú
<listcomp>F   s    ÿÿz8PITSolver.forward.<locals>.pair_loss.<locals>.<listcomp>)ÚsumÚ	enumerateÚlen)Úpermutationr#   r   r   Ú	pair_lossD   s   þÿûz$PITSolver.forward.<locals>.pair_lossr   c                    s   g | ]}ˆ |ƒ‘qS r   r   ©r    Úp)r+   r   r   r&   P   s    z%PITSolver.forward.<locals>.<listcomp>é   )Údim)ÚdeviceÚdtypeé   c                 S   s   g | ]}d ‘qS )r.   r   )r    Ú_r   r   r   r&   _   s    éÿÿÿÿ)r0   c              	      s8   g | ]\‰ }t  ‡ ‡‡‡‡fd d„t|ƒD ƒ¡ ¡ ‘qS )c                    s:   g | ]\}}ˆˆj ˆ| ˆ   d ¡ˆ| ˆ   d ¡ƒ‘qS )r   )r   Ú	unsqueezer   )Úbatchr$   r   r%   r   r   r   r&   h   s    ûýÿz0PITSolver.forward.<locals>.<listcomp>.<listcomp>)ÚtorchÚtensorr(   Úmeanr,   r#   )r6   r   r&   f   s    öúÿ	ö)r   r)   r   Úlistr   r0   r   Úranger7   ÚstackÚminÚindex_selectr8   Úlongr   ÚshapeÚviewr9   r/   Úexpandr5   ÚgatherÚtoÚunbindr(   Údetachr   ÚnameÚdict)r   r%   r$   Úothersr   Únum_spkr0   Úall_permutationsÚlossesÚlossÚperm_r   r   Únew_vÚBÚLÚrestÚshapesÚperm0r   )r$   r+   r   r%   r   r   r   Úforward(   sN   $

ý ,
"õõÿzPITSolver.forward)r   TF)Ú__name__Ú
__module__Ú__qualname__r   r
   rU   Ú__classcell__r   r   r   r   r   
   s    ûþr   )
Úcollectionsr   Ú	itertoolsr   r7   Ú$espnet2.enh.loss.criterions.abs_lossr   Ú%espnet2.enh.loss.wrappers.abs_wrapperr   r   r   r   r   r   Ú<module>   s    