code: def forward_core(self, nnet_output, ys, hlens, ylens):
      # (1) Find the shape
      (B, T, _), U = nnet_output.size(), max(ylens)
  
      # (2) Build DenseFsaVec and CTC graphs
      supervision = torch.stack(
          [torch.arange(B), torch.zeros(B), hlens.cpu()], dim=1
      ).int()
  
      dense_fsa_vec = k2.DenseFsaVec(nnet_output, supervision)
      ctc_graphs = k2.ctc_graph(ys).to(nnet_output.device)
  
      # (3) Intersection for twice
      #     One is for back-prop, the other is to find arc_maps
      #     A. In K2, the arc_maps are not provided in user API.
      #     This would slightly slow down the training but can
      #     ensure that code is compatible with original K2 API
      #     B. Always use very large beam size to avoid any pruning
      #     so the results are identical to vanilla CTC if no
      #     risk values are applied.
      lats = k2.intersect_dense(ctc_graphs, dense_fsa_vec, 1e20)
  
      with torch.no_grad():
          ragged_lat, arc_map_a, arc_map_b = _k2.intersect_dense(
              a_fsas=ctc_graphs.arcs,
              b_fsas=dense_fsa_vec.dense_fsa_vec,
              a_to_b_map=None,
              output_beam=1e20,
          )
  
          (arc_u_idx, arc_t_idx, arc_k_idx, arc_b_idx), (
              state_u_idx,
              state_t_idx,
              state_k_idx,
              state_b_idx,
          ) = self.find_all_index(
              ragged_lat,
              ctc_graphs,
              dense_fsa_vec,
              arc_map_a,
              arc_map_b,
          )
  
      # (4) Rearrange all forward-backward variables and emission probabilities
      # into matrices. Always use double precision to reduce accumulated error.
      forward_scores = lats.get_forward_scores(True, True)
      backward_scores = lats.get_backward_scores(True, True)
  
      alpha = torch.ones([B, 2 * U + 3, T + 2]).double().to(
          nnet_output.device
      ) * float("-inf")
      beta = torch.ones([B, 2 * U + 3, T + 2]).double().to(
          nnet_output.device
      ) * float("-inf")
  
      alpha[state_b_idx, state_u_idx, state_t_idx] = forward_scores
      beta[state_b_idx, state_u_idx, state_t_idx] = backward_scores
      alpha, beta = alpha[:, 1:-1, 1:-1], beta[:, 1:-1, 1:-1]
  
      p = torch.ones([B, 2 * U + 1, T]).double().to(
          nnet_output.device
      ) * float("-inf")
      state_u_idx = torch.clip(state_u_idx - 1, min=0, max=2 * U)
      state_t_idx = torch.clip(state_t_idx - 1, min=0, max=T - 1)
      p[state_b_idx, state_u_idx, state_t_idx] = nnet_output.double()[
          state_b_idx, state_t_idx, state_k_idx
      ]
      p = torch.where(torch.isinf(alpha), float("-inf"), p)
  
      # (5) Compute the summed posterior within each group;
      #     apply the risk value and compute the overall loss
      if self.group_strategy in ["end", "end_mean"]:
          # Only consider non-blank tokens
          alpha = alpha[:, 1::2]
          beta = beta[:, 1::2]
          p = p[:, 1::2]
  
          beta_prime = log_substraction_exp(
              beta[:, :, :-1], beta[:, :, 1:] + p[:, :, 1:]
          )
          beta_prime = torch.cat([beta_prime, beta[:, :, -1:]], dim=-1)
          loss_state = alpha + beta_prime
  
          # Apply risk values
          loss_state = loss_state + self.get_risk_scores(
              loss_state, hlens, self.risk_factor
          )
  
          # aggregate all groups
          loss_u = torch.logsumexp(loss_state, dim=2)
          mask = ~torch.isinf(loss_u)
  
          if self.group_strategy == "end_mean":
              loss_fsas = torch.where(mask, loss_u, 0.0).sum(
                  1
              ) / mask.double().sum(1)
  
          else:
              loss_fsas = loss_u[
                  torch.arange(B).long(), mask.long().sum(1) - 1
              ]
  
          return -loss_fsas
  
      # Users may design their own group strategy here
      else:
          raise NotImplementedError
  
file_path: espnet/espnet2/asr/bayes_risk_ctc.py
imports: import logging
  import _k2
  import k2
  import torch
label_desc: Use image node_id 3 for calling the BayesRiskCTC obj's underlying member method code with example usage: obj.forward_core(nnet_output, ys, hlens, ylens) and returns: unknown