class_docstr: An RGCN layer from [schlichtkrull2018]_ updated to match the official implementation.
  
  This layer uses separate decompositions for forward and backward edges (i.e., "normal" and implicitly created
  inverse relations), as well as a separate transformation for self-loops.
  
  Ignoring dropouts, decomposition and normalization, it can be written as
  
  .. math ::
      y_i = \sigma(
          W^s x_i
          + \sum_{(e_j, r, e_i) \in \mathcal{T}} W^f_r x_j
          + \sum_{(e_i, r, e_j) \in \mathcal{T}} W^b_r x_j
          + b
      )
  
  where $b, W^s, W^f_r, W^b_r$ are trainable weights. $W^f_r, W^b_r$ are relation-specific, and commonly enmploy a
  weight-sharing mechanism, cf. Decomposition. $\sigma$ is an activation function. The individual terms in both sums
  are typically weighted. This is implemented by EdgeWeighting. Moreover, RGCN employs an edge-dropout, however,
  this needs to be done outside of an individual layer, since the same edges are dropped across all layers. In
  contrast, the self-loop dropout is layer-specific.
class_docstr_tok: ["An","RGCN","layer","from","[","schlichtkrull2018","]","_","updated","to","match","the","official","implementation",".","This","layer","uses","separate","decompositions","for","forward","and","backward","edges","(","i.e.",",","``","normal","''","and","implicitly","created","inverse","relations",")",",","as","well","as","a","separate","transformation","for","self-loops",".","Ignoring","dropouts",",","decomposition","and","normalization",",","it","can","be","written","as","..","math",":",":","y_i","=","\\sigma","(","W^s","x_i","+","\\sum_","{","(","e_j",",","r",",","e_i",")","\\in","\\mathcal","{","T","}","}","W^f_r","x_j","+","\\sum_","{","(","e_i",",","r",",","e_j",")","\\in","\\mathcal","{","T","}","}","W^b_r","x_j","+","b",")","where","$","b",",","W^s",",","W^f_r",",","W^b_r","$","are","trainable","weights",".","$","W^f_r",",","W^b_r","$","are","relation-specific",",","and","commonly","enmploy","a","weight-sharing","mechanism",",","cf",".","Decomposition",".","$","\\sigma","$","is","an","activation","function",".","The","individual","terms","in","both","sums","are","typically","weighted",".","This","is","implemented","by","EdgeWeighting",".","Moreover",",","RGCN","employs","an","edge-dropout",",","however",",","this","needs","to","be","done","outside","of","an","individual","layer",",","since","the","same","edges","are","dropped","across","all","layers",".","In","contrast",",","the","self-loop","dropout","is","layer-specific","."]
docstr: Initialize the layer.
  
  :param input_dim: >0
      the input dimension
  :param num_relations:
      the number of relations
  :param output_dim: >0
      the output dimension. If none is given, use the input dimension.
  :param use_bias:
      whether to use a trainable bias
  :param activation:
      the activation function to use. Defaults to None, i.e., the identity function serves as activation.
  :param activation_kwargs:
      additional keyword-based arguments passed to the activation function for instantiation
  :param self_loop_dropout: 0 <= self_loop_dropout <= 1
      the dropout to use for self-loops
  :param decomposition:
      the decomposition to use, cf. Decomposition and decomposition_resolver
  :param decomposition_kwargs:
      the keyword-based arguments passed to the decomposition for instantiation
code: def __init__(
      self,
      num_relations: int,
      input_dim: int = 32,
      output_dim: Optional[int] = None,
      use_bias: bool = True,
      activation: Hint[nn.Module] = None,
      activation_kwargs: Optional[Mapping[str, Any]] = None,
      self_loop_dropout: float = 0.2,
      decomposition: Hint[Decomposition] = None,
      decomposition_kwargs: Optional[Mapping[str, Any]] = None,
  ):
      """
      Initialize the layer.
  
      :param input_dim: >0
          the input dimension
      :param num_relations:
          the number of relations
      :param output_dim: >0
          the output dimension. If none is given, use the input dimension.
      :param use_bias:
          whether to use a trainable bias
      :param activation:
          the activation function to use. Defaults to None, i.e., the identity function serves as activation.
      :param activation_kwargs:
          additional keyword-based arguments passed to the activation function for instantiation
      :param self_loop_dropout: 0 <= self_loop_dropout <= 1
          the dropout to use for self-loops
      :param decomposition:
          the decomposition to use, cf. Decomposition and decomposition_resolver
      :param decomposition_kwargs:
          the keyword-based arguments passed to the decomposition for instantiation
      """
      super().__init__()
      # cf. https://github.com/MichSchli/RelationPrediction/blob/c77b094fe5c17685ed138dae9ae49b304e0d8d89/code/encoders/message_gcns/gcn_basis.py#L22-L24  # noqa: E501
      # there are separate decompositions for forward and backward relations.
      # the self-loop weight is not decomposed.
      self.fwd = decomposition_resolver.make(
          query=decomposition,
          pos_kwargs=decomposition_kwargs,
          input_dim=input_dim,
          output_dim=output_dim,
          num_relations=num_relations,
      )
      self.bwd = decomposition_resolver.make(
          query=decomposition,
          pos_kwargs=decomposition_kwargs,
          input_dim=input_dim,
          output_dim=output_dim,
          num_relations=num_relations,
      )
      self.self_loop = nn.Linear(
          in_features=input_dim,
          out_features=self.fwd.output_dim,
          bias=use_bias,
      )
      self.dropout = nn.Dropout(p=self_loop_dropout)
      self.activation = activation_resolver.make_safe(
          query=activation, pos_kwargs=activation_kwargs
      )
  
imports: import logging
  import math
  from abc import ABC, abstractmethod
  from typing import Any, Iterable, Mapping, Optional, Sequence
  import torch
  from class_resolver import ClassResolver, Hint, HintOrType, OptionalKwargs
  from class_resolver.contrib.torch import activation_resolver
  from docdata import parse_docdata
  from torch import nn
  from .init import uniform_norm_p1_, xavier_normal_
  from .representation import LowRankRepresentation, Representation
  from .utils import ShapeError, adjacency_tensor_to_stacked_matrix, use_horizontal_stacking
  from .weighting import EdgeWeighting, edge_weight_resolver
  from ..triples import CoreTriplesFactory
  from ..utils import ExtraReprMixin, einsum
label_desc: Use image node_id 1 to create a new RGCNLayer object from inherited base classes: nn with example: obj = RGCNLayer(num_relations, input_dim, output_dim, use_bias, activation, activation_kwargs, _loop_dropout, decomposition, decomposition_kwargs)