docstr: :param input_memories: [num-inputs-flattened, D]
  :param input_memories_origin_idx: [num-inputs-flattened]
  :param initial_states: [num-targets, H]
  :param input_token_ids: [num-targets, max-seq-size-1]
  
  :return: the logprobs for all copying locations and the logprobs for all elements in the vocabulary
docstr_tok: [":","param","input_memories",":","[","num-inputs-flattened",",","D","]",":","param","input_memories_origin_idx",":","[","num-inputs-flattened","]",":","param","initial_states",":","[","num-targets",",","H","]",":","param","input_token_ids",":","[","num-targets",",","max-seq-size-1","]",":","return",":","the","logprobs","for","all","copying","locations","and","the","logprobs","for","all","elements","in","the","vocabulary"]
code: def _compute_logprobs(
      self,
      initial_states,
      input_memories,
      input_memories_origin_idx,
      input_token_ids,
  ):
      """
      :param input_memories: [num-inputs-flattened, D]
      :param input_memories_origin_idx: [num-inputs-flattened]
      :param initial_states: [num-targets, H]
      :param input_token_ids: [num-targets, max-seq-size-1]
  
      :return: the logprobs for all copying locations and the logprobs for all elements in the vocabulary
      """
      target_token_embeddings = self.__dropout(
          self.__embedding_layer(input_token_ids)
      )  # [num-targets, max-seq-size - 1, H]
      output_states, output_gru_state = self.__output_gru(
          target_token_embeddings, initial_states.unsqueeze(0)
      )
      output_states = (
          output_states.contiguous()
      )  # [num-targets, max-seq-size, H]
  
      # Standard and copy attention representations
      standard_attention_reps = self.__memories_to_standard_attention(
          input_memories
      )  # [num-inputs-flattened, H]
  
      copy_attention_reps = self.__memories_to_copy_attention(
          input_memories
      )  # [num-inputs-flattened, H]
      copy_attention_reps = self.__dropout(copy_attention_reps)
  
      # Compute attention scores [num-inputs-flattened, max-seq-size]
      output_states_per_input = output_states[
          input_memories_origin_idx
      ]  # [num-inputs-flattened, max-seq-size, H]
      standard_attention_scores = torch.einsum(
          "ilh,ih->il", output_states_per_input, standard_attention_reps
      )  # [num-inputs-flattened, max-seq-size]
      copy_attention_scores = torch.einsum(
          "ilh,ih->il", output_states_per_input, copy_attention_reps
      )  # [num-inputs-flattened, max-seq-size]
  
      # For some reason scatter_softmax doesn't work here
      standard_attention_logprobs = scatter_log_softmax(
          standard_attention_scores,
          index=input_memories_origin_idx,
          dim=0,
          eps=0,
      )  # [num-inputs-flattened, max-seq-size]
  
      # Compute standard attention output
      standard_attention_mul = torch.einsum(
          "il,ih->ilh",
          torch.exp(standard_attention_logprobs),
          standard_attention_reps,
      )
      standard_attention_out = scatter_add(
          standard_attention_mul, index=input_memories_origin_idx, dim=0
      )  # [num-targets, max-seq-size, H]
      target_scores = (
          torch.einsum(
              "blh,hd,vd->blv",
              torch.cat(
                  (
                      self.__dropout(standard_attention_out),
                      output_states,
                  ),
                  dim=-1,
              ),
              self.__hidden_to_vocab,
              self.__dropout(self.__embedding_layer.weight),
          )
          + self.__vocab_bias
      )  # [num-targets, max-seq-size, vocab-size]
  
      # A "manual" log_softmax
      total_copy_scores = scatter_logsumexp(
          copy_attention_scores,
          index=input_memories_origin_idx,
          dim=0,
          eps=0,
      )  # [num-targets, max-seq-size]
      all_scores = torch.cat(
          (target_scores, total_copy_scores.unsqueeze(-1)), dim=-1
      )  # [num-targets, max-seq-size, vocab-size + 1]
      normalizing_const = torch.logsumexp(
          all_scores, dim=-1
      )  # [num-targets, max-seq-size]
  
      target_logprobs = target_scores - normalizing_const.unsqueeze(
          -1
      )  # [num-targets, max-seq-size, vocab-size]
      copy_logprobs = (
          copy_attention_scores
          - normalizing_const[input_memories_origin_idx]
      )  # [num-inputs-flattened, max-seq-size]
  
      # Do probabilities actually sum up to 1?
      # sum_logcopy = scatter_logsumexp(copy_logprobs, index=input_memories_origin_idx, dim=0, eps=0) # [num-targets, max-seq-size]
      # sum_targets = torch.logsumexp(target_logprobs, dim=-1)                          # [num-targets, max-seq-size]
      # torch.allclose(torch.logsumexp(torch.stack([sum_logcopy, sum_targets], dim=-1), dim=-1), torch.zeros_like(sum_logcopy), atol=.0001)
  
      return copy_logprobs, target_logprobs, output_gru_state
  
imports: from typing_extensions import Final
  import logging
  import math
  import numpy
  import torch
  import torch.nn
  from dpu_utils.mlutils import Vocabulary
  from torch_scatter import scatter_add
  from torch_scatter.composite import scatter_log_softmax, scatter_logsumexp
  from typing import Any, Counter, Dict, List, NamedTuple, Tuple, Union
  from ptgnn.baseneuralmodel import AbstractNeuralModel
label_desc: Use image node_id 2 for calling the GruCopyingDecoder obj's underlying member method code with example usage: obj._compute_logprobs(initial_states, input_memories, input_memories_origin_idx, input_token_ids) and returns: copy_logprobs,  target_logprobs,  output_gru_state