class_docstr: Relational graph convolution layer from `Modeling Relational Data with Graph
  Convolutional Networks <https://arxiv.org/abs/1703.06103>`__
  
  It can be described as below:
  
  .. math::
  
     h_i^{(l+1)} = \sigma(\sum_{r\in\mathcal{R}}
     \sum_{j\in\mathcal{N}^r(i)}\frac{1}{c_{i,r}}W_r^{(l)}h_j^{(l)}+W_0^{(l)}h_i^{(l)})
  
  where :math:`\mathcal{N}^r(i)` is the neighbor set of node :math:`i` w.r.t. relation
  :math:`r`. :math:`c_{i,r}` is the normalizer equal
  to :math:`|\mathcal{N}^r(i)|`. :math:`\sigma` is an activation function. :math:`W_0`
  is the self-loop weight.
  
  The basis regularization decomposes :math:`W_r` by:
  
  .. math::
  
     W_r^{(l)} = \sum_{b=1}^B a_{rb}^{(l)}V_b^{(l)}
  
  where :math:`B` is the number of bases, :math:`V_b^{(l)}` are linearly combined
  with coefficients :math:`a_{rb}^{(l)}`.
  
  The block-diagonal-decomposition regularization decomposes :math:`W_r` into :math:`B`
  number of block diagonal matrices. We refer :math:`B` as the number of bases.
  
  The block regularization decomposes :math:`W_r` by:
  
  .. math::
  
     W_r^{(l)} = \oplus_{b=1}^B Q_{rb}^{(l)}
  
  where :math:`B` is the number of bases, :math:`Q_{rb}^{(l)}` are block
  bases with shape :math:`R^{(d^{(l+1)}/B)*(d^{l}/B)}`.
  
  Parameters
  ----------
  in_feat : int
      Input feature size; i.e, the number of dimensions of :math:`h_j^{(l)}`.
  out_feat : int
      Output feature size; i.e., the number of dimensions of :math:`h_i^{(l+1)}`.
  num_rels : int
      Number of relations. .
  regularizer : str
      Which weight regularizer to use "basis" or "bdd".
      "basis" is short for basis-diagonal-decomposition.
      "bdd" is short for block-diagonal-decomposition.
  num_bases : int, optional
      Number of bases. If is none, use number of relations. Default: ``None``.
  bias : bool, optional
      True if bias is added. Default: ``True``.
  activation : callable, optional
      Activation function. Default: ``None``.
  self_loop : bool, optional
      True to include self loop message. Default: ``True``.
  low_mem : bool, optional
      True to use low memory implementation of relation message passing function. Default: False.
      This option trades speed with memory consumption, and will slowdown the forward/backward.
      Turn it on when you encounter OOM problem during training or evaluation. Default: ``False``.
  dropout : float, optional
      Dropout rate. Default: ``0.0``
  layer_norm: float, optional
      Add layer norm. Default: ``False``
  
  Examples
  --------
  >>> import dgl
  >>> import numpy as np
  >>> import tensorflow as tf
  >>> from dgl.nn import RelGraphConv
  >>>
  >>> with tf.device("CPU:0"):
  >>>     g = dgl.graph(([0,1,2,3,2,5], [1,2,3,4,0,3]))
  >>>     feat = tf.ones((6, 10))
  >>>     conv = RelGraphConv(10, 2, 3, regularizer='basis', num_bases=2)
  >>>     etype = tf.convert_to_tensor(np.array([0,1,2,0,1,2]).astype(np.int64))
  >>>     res = conv(g, feat, etype)
  >>>     res
  <tf.Tensor: shape=(6, 2), dtype=float32, numpy=
  array([[-0.02938664,  1.7932655 ],
      [ 0.1146394 ,  0.48319   ],
      [-0.02938664,  1.7932655 ],
      [ 1.2054908 , -0.26098895],
      [ 0.1146394 ,  0.48319   ],
      [ 0.75915515,  1.1454091 ]], dtype=float32)>
  
  >>> # One-hot input
  >>> with tf.device("CPU:0"):
  >>>     one_hot_feat = tf.convert_to_tensor(np.array([0,1,2,3,4,5]).astype(np.int64))
  >>>     res = conv(g, one_hot_feat, etype)
  >>>     res
  <tf.Tensor: shape=(6, 2), dtype=float32, numpy=
  array([[-0.24205256, -0.7922753 ],
      [ 0.62085056,  0.4893622 ],
      [-0.9484881 , -0.26546806],
      [-0.2163915 , -0.12585883],
      [-0.14293689,  0.77483284],
      [ 0.091169  , -0.06761569]], dtype=float32)>
docstr: Message function for block-diagonal-decomposition regularizer
docstr_tok: ["Message","function","for","block-diagonal-decomposition","regularizer"]
code: def bdd_message_func(self, edges):
      """Message function for block-diagonal-decomposition regularizer"""
      if (edges.src["h"].dtype == tf.int64) and len(
          edges.src["h"].shape
      ) == 1:
          raise TypeError(
              "Block decomposition does not allow integer ID feature."
          )
  
      # calculate msg @ W_r before put msg into edge
      # if src is th.int64 we expect it is an index select
      if self.low_mem:
          etypes, _ = tf.unique(edges.data["type"])
          msg = tf.zeros([edges.src["h"].shape[0], self.out_feat])
          idx = tf.range(edges.src["h"].shape[0])
          for etype in etypes:
              loc = edges.data["type"] == etype
              w = tf.reshape(
                  self.weight[etype],
                  (self.num_bases, self.submat_in, self.submat_out),
              )
              src = tf.reshape(
                  tf.boolean_mask(edges.src["h"], loc),
                  (-1, self.num_bases, self.submat_in),
              )
              sub_msg = tf.einsum("abc,bcd->abd", src, w)
              sub_msg = tf.reshape(sub_msg, (-1, self.out_feat))
              indices = tf.reshape(tf.boolean_mask(idx, loc), (-1, 1))
              msg = tf.tensor_scatter_nd_update(msg, indices, sub_msg)
      else:
          weight = tf.reshape(
              tf.gather(self.weight, edges.data["type"]),
              (-1, self.submat_in, self.submat_out),
          )
          node = tf.reshape(edges.src["h"], (-1, 1, self.submat_in))
          msg = tf.reshape(tf.matmul(node, weight), (-1, self.out_feat))
      if "norm" in edges.data:
          msg = msg * edges.data["norm"]
      return {"msg": msg}
  
file_path: dgl/python/dgl/nn/tensorflow/conv/relgraphconv.py
imports: import tensorflow
  from tensorflow.keras import layers
  from ....None import function
  from ..None import utils
label_desc: Use image node_id 3 for calling the RelGraphConv obj's underlying member method code with example usage: obj.bdd_message_func(edges) and returns: dict