class_docstr: An anchor tokenizer, which first partitions the graph using METIS.
  
  We use the binding by :mod:`torch_sparse`. The METIS graph partitioning algorithm is described here:
  http://glaros.dtc.umn.edu/gkhome/metis/metis/overview
class_docstr_tok: ["An","anchor","tokenizer",",","which","first","partitions","the","graph","using","METIS",".","We","use","the","binding","by",":","mod",":","`","torch_sparse","`",".","The","METIS","graph","partitioning","algorithm","is","described","here",":","http",":","\/\/glaros.dtc.umn.edu\/gkhome\/metis\/metis\/overview"]
code: def __call__(
      self,
      mapped_triples: MappedTriples,
      num_tokens: int,
      num_entities: int,
      num_relations: int,
  ) -> Tuple[int, torch.LongTensor]:  # noqa: D102
      try:
          import torch_sparse
      except ImportError as err:
          raise ImportError(
              f"{self.__class__.__name__} requires `torch_sparse` to be installed."
          ) from err
  
      logger.info(
          f"Partitioning the graph into {self.num_partitions} partitions."
      )
      edge_index = get_edge_index(mapped_triples=mapped_triples)
      # To prevent possible segfaults in the METIS C code, METIS expects a graph
      # (1) without self-loops; (2) with inverse edges added; (3) with unique edges only
      # https://github.com/KarypisLab/METIS/blob/94c03a6e2d1860128c2d0675cbbb86ad4f261256/libmetis/checkgraph.c#L18
      row, col = prepare_edges_for_metis(edge_index=edge_index)
      re_ordered_adjacency, bound, perm = torch_sparse.partition(
          src=torch_sparse.SparseTensor(
              row=row,
              col=col,
              sparse_sizes=(num_entities, num_entities),
          ).to(device=self.device),
          num_parts=self.num_partitions,
          recursive=True,
      )
      re_ordered_adjacency = re_ordered_adjacency.cpu()
      sizes = bound.diff()
      logger.info(
          f"Partition sizes: min: {sizes.min().item()}, max: {sizes.max().item()}"
      )
  
      # select independently per partition
      vocabulary_size = 0
      assignment = []
      edge_count = 0
      for low, high in more_itertools.pairwise(bound.tolist()):
          # select adjacency part;
          # note: the indices will automatically be in [0, ..., high - low), since they are *local* indices
          edge_index = (
              re_ordered_adjacency[low:high, low:high]
              .to_torch_sparse_coo_tensor()
              .coalesce()
              .indices()
          )
          edge_count += edge_index.shape[1]
          num_entities = high - low
          this_vocabulary_size, this_assignment = super()._call(
              edge_index=edge_index,
              num_tokens=num_tokens,
              num_entities=num_entities,
          )
          assert this_assignment.shape[0] == num_entities
  
          # offset
          mask = this_assignment < 0
          this_assignment = this_assignment + vocabulary_size
          this_assignment[mask] = -1
  
          # the -1 comes from the shared padding token
          vocabulary_size += this_vocabulary_size - 1
  
          # note: permutation will be later on reverted
          assignment.append(this_assignment)
  
      # add back 1 for the shared padding token
      vocabulary_size += 1
      total_edges = mapped_triples.shape[0]
      logger.info(
          f"Partitioned anchor tokenization lead to ignoring "
          f"{format_relative_comparison(part=total_edges - edge_count, total=total_edges)} connections.",
      )
      # TODO: check if perm is used correctly
      return vocabulary_size, torch.cat(assignment, dim=0)[perm]
  
imports: import logging
  import pathlib
  from abc import abstractmethod
  from collections import defaultdict
  from typing import Collection, Mapping, Optional, Tuple
  import more_itertools
  import numpy
  import torch
  from class_resolver import ClassResolver, HintOrType, OptionalKwargs
  from .anchor_search import AnchorSearcher, anchor_searcher_resolver
  from .anchor_selection import AnchorSelection, anchor_selection_resolver
  from .loader import PrecomputedTokenizerLoader, precomputed_tokenizer_loader_resolver
  from .utils import prepare_edges_for_metis, random_sample_no_replacement
  from ...constants import PYKEEN_MODULE
  from ...typing import DeviceHint, MappedTriples
  from ...utils import format_relative_comparison, get_edge_index, resolve_device
label_desc: Use image node_id 2 for calling the MetisAnchorTokenizer obj's underlying member method code with example usage: obj.__call__(mapped_triples, num_tokens, num_entities, num_relations) and returns: vocabulary_size,  torch