class_docstr: Evaluation loop using 1:n scoring.
  
  For brevity, we only describe evaluation for tail prediction. Let $(h, r, t) \in \mathcal{T}_{eval}$ denote an
  evaluation triple. Then, we calculate scores for all triples $(h, r, t')$ with $t' \in \mathcal{E}$, i.e., for
  replacing the true tail $t$ by all entities.
class_docstr_tok: ["Evaluation","loop","using","1",":","n","scoring",".","For","brevity",",","we","only","describe","evaluation","for","tail","prediction",".","Let","$","(","h",",","r",",","t",")","\\in","\\mathcal","{","T","}","_","{","eval","}","$","denote","an","evaluation","triple",".","Then",",","we","calculate","scores","for","all","triples","$","(","h",",","r",",","t","'",")","$","with","$","t","'","\\in","\\mathcal","{","E","}","$",",","i.e.",",","for","replacing","the","true","tail","$","t","$","by","all","entities","."]
code: def process_batch(
      self, batch: Mapping[Target, MappedTriples]
  ) -> None:  # noqa: D102
      # note: most of the time, this loop will only make a single iteration, since the evaluation dataset typically is
      #       not shuffled, and contains evaluation ranking tasks sorted by target
      for target, (hrt_batch, filter_batch) in batch.items():
          # TODO: in theory, we could make a single score calculation for e.g.,
          # {(h, r, t1), (h, r, t1), ..., (h, r, tk)}
          # predict scores for all candidates
          scores = self.model.predict(
              hrt_batch=hrt_batch, target=target, mode=self.mode
          )
          true_scores = dense_positive_mask = None
  
          # filter scores
          if self.evaluator.filtered:
              if filter_batch is None:
                  raise AssertionError(
                      "Filter indices are required to filter scores."
                  )
              # extract true scores
              batch_ids = torch.arange(
                  scores.shape[0], device=scores.device
              )
              target_ids = hrt_batch[:, TARGET_TO_INDEX[target]]
              true_scores = scores[batch_ids, target_ids, None]
              # replace by nan
              scores = filter_scores_(
                  scores=scores, filter_batch=filter_batch
              )
              # rewrite true scores
              scores[batch_ids, target_ids] = true_scores[:, 0]
  
          # create dense positive masks
          # TODO: afaik, dense positive masks are not used on GPU -> we do not need to move the masks around
          elif self.evaluator.requires_positive_mask:
              if filter_batch is None:
                  raise AssertionError(
                      "Filter indices are required to create dense positive masks."
                  )
              dense_positive_mask = torch.zeros_like(
                  scores, dtype=torch.bool, device=filter_batch.device
              )
              dense_positive_mask[
                  filter_batch[:, 0], filter_batch[:, 0]
              ] = True
  
          # delegate processing of scores to the evaluator
          self.evaluator.process_scores_(
              hrt_batch=hrt_batch,
              target=target,
              scores=scores,
              true_scores=true_scores,
              dense_positive_mask=dense_positive_mask,
          )
  
imports: import dataclasses
  import logging
  from abc import abstractmethod
  from collections import defaultdict
  from typing import Any, Collection, DefaultDict, Generic, Iterable, List, Mapping, Optional, Tuple, TypeVar, Union, cast
  import numpy
  import pandas
  import torch
  from class_resolver import HintOrType, OptionalKwargs
  from torch.utils.data import Dataset
  from torch.utils.data.dataloader import DataLoader
  from torch_max_mem import maximize_memory_utilization
  from tqdm.auto import tqdm
  from typing_extensions import TypeAlias
  from .evaluator import Evaluator, MetricResults, filter_scores_
  from ..constants import COLUMN_LABELS, TARGET_TO_INDEX
  from ..models import Model
  from ..triples import CoreTriplesFactory, get_mapped_triples
  from ..typing import LABEL_HEAD, LABEL_TAIL, InductiveMode, MappedTriples, OneOrSequence, Target
  from ..utils import upgrade_to_sequence
label_desc: Use image node_id 3 for calling the LCWAEvaluationLoop obj's underlying member method code with example usage: obj.process_batch(batch) without return types