class_docstr: The PPFNet operator from the `"PPFNet: Global Context Aware Local
  Features for Robust 3D Point Matching" <https://arxiv.org/abs/1802.02669>`_
  paper.
  
  .. math::
      \mathbf{x}^{\prime}_i = \gamma_{\mathbf{\Theta}} \left( \max_{j \in
      \mathcal{N}(i) \cup \{ i \}} h_{\mathbf{\Theta}} ( \mathbf{x}_j, \|
      \mathbf{d_{j,i}} \|, \angle(\mathbf{n}_i, \mathbf{d_{j,i}}),
      \angle(\mathbf{n}_j, \mathbf{d_{j,i}}), \angle(\mathbf{n}_i,
      \mathbf{n}_j) \right)
  
  where :math:`\gamma_{\mathbf{\Theta}}` and :math:`h_{\mathbf{\Theta}}`
  denote neural networks, *.i.e.* MLPs, which takes in node features and
  :class:`torch_geometric.transforms.PointPairFeatures`.
  
  Args:
      local_nn (torch.nn.Module, optional): A neural network
          :math:`h_{\mathbf{\Theta}}` that maps node features :obj:`x` and
          relative spatial coordinates :obj:`pos_j - pos_i` of shape
          :obj:`[-1, in_channels + num_dimensions]` to shape
          :obj:`[-1, out_channels]`, *e.g.*, defined by
          :class:`torch.nn.Sequential`. (default: :obj:`None`)
      global_nn (torch.nn.Module, optional): A neural network
          :math:`\gamma_{\mathbf{\Theta}}` that maps aggregated node features
          of shape :obj:`[-1, out_channels]` to shape :obj:`[-1,
          final_out_channels]`, *e.g.*, defined by
          :class:`torch.nn.Sequential`. (default: :obj:`None`)
      add_self_loops (bool, optional): If set to :obj:`False`, will not add
          self-loops to the input graph. (default: :obj:`True`)
      **kwargs (optional): Additional arguments of
          :class:`torch_geometric.nn.conv.MessagePassing`.
  
  Shapes:
      - **input:**
        node features :math:`(|\mathcal{V}|, F_{in})` or
        :math:`((|\mathcal{V_s}|, F_{s}), (|\mathcal{V_t}|, F_{t}))`
        if bipartite,
        positions :math:`(|\mathcal{V}|, 3)` or
        :math:`((|\mathcal{V_s}|, 3), (|\mathcal{V_t}|, 3))` if bipartite,
        point normals :math:`(|\mathcal{V}, 3)` or
        :math:`((|\mathcal{V_s}|, 3), (|\mathcal{V_t}|, 3))` if bipartite,
        edge indices :math:`(2, |\mathcal{E}|)`
      - **output:** node features :math:`(|\mathcal{V}|, F_{out})` or
        :math:`(|\mathcal{V}_t|, F_{out})` if bipartite
code: def __init__(
      self,
      local_nn: Optional[Callable] = None,
      global_nn: Optional[Callable] = None,
      add_self_loops: bool = True,
      **kwargs,
  ):
      kwargs.setdefault("aggr", "max")
      super().__init__(**kwargs)
  
      self.local_nn = local_nn
      self.global_nn = global_nn
      self.add_self_loops = add_self_loops
  
      self.reset_parameters()
  
file_path: pytorch_geometric/torch_geometric/nn/conv/ppf_conv.py
imports: from typing import Callable, Optional, Union
  import torch
  from torch import Tensor
  from torch_geometric.nn.conv import MessagePassing
  from torch_geometric.nn.inits import reset
  from torch_geometric.typing import Adj, OptTensor, PairOptTensor, PairTensor, SparseTensor, torch_sparse
  from torch_geometric.utils import add_self_loops, remove_self_loops
label_desc: Use image node_id 1 to create a new PPFConv object from inherited base classes: MessagePassing with example: obj = PPFConv(local_nn, global_nn, add__loops)