docstr: Permutation invariant training solver.
  
  Args:
      ref (List[torch.Tensor]): [(batch, ...), ...] x n_spk
      infs (Union[List[torch.Tensor], List[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
docstr_tok: ["Permutation","invariant","training","solver",".","Args",":","ref","(","List","[","torch.Tensor","]",")",":","[","(","batch",",","...",")",",","...","]","x","n_spk","infs","(","Union","[","List","[","torch.Tensor","]",",","List","[","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"]
code: def forward(self, ref, infs, others={}):
      """Permutation invariant training solver.
  
      Args:
          ref (List[torch.Tensor]): [(batch, ...), ...] x n_spk
          infs (Union[List[torch.Tensor], List[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
      """
      losses = 0.0
      # In single-layer case, the model only estimates waveforms in the last layer.
      # The shape of infs is List[torch.Tensor]
      if not isinstance(infs[0], (tuple, list)) and len(infs) == len(
          ref
      ):
          loss, stats, others = self.solver(ref, infs, others)
          losses = loss
      # In multi-layer case, weighted-sum the PIT loss of each layer
      # The shape of ins is List[List[torch.Tensor]]
      else:
          for idx, inf in enumerate(infs):
              loss, stats, others = self.solver(ref, inf, others)
              if self.layer_weights is not None:
                  losses = losses + loss * self.layer_weights[idx]
              else:
                  losses = losses + loss * (idx + 1) * (1.0 / len(infs))
          losses = losses / len(infs)
      return losses, stats, others
  
imports: from espnet2.enh.loss.criterions.abs_loss import AbsEnhLoss
  from espnet2.enh.loss.wrappers.abs_wrapper import AbsLossWrapper
  from espnet2.enh.loss.wrappers.pit_solver import PITSolver
label_desc: Use image node_id 2 for calling the MultiLayerPITSolver obj's underlying member method code with example usage: obj.forward(ref, infs, others) and returns: losses,  stats,  others