class_docstr: Attentional Aggregator for GraphSAGE implemented with Keras base layer
  
  Implements the aggregator of Veličković et al. "Graph Attention Networks" ICLR 2018
  
  Args:
      output_dim (int): Output dimension
      bias (bool): Optional bias
      act (Callable or str): name of the activation function to use (must be a
          Keras activation function), or alternatively, a TensorFlow operation.
class_docstr_tok: ["Attentional","Aggregator","for","GraphSAGE","implemented","with","Keras","base","layer","Implements","the","aggregator","of","Veli\u010dkovi\u0107","et","al",".","``","Graph","Attention","Networks","''","ICLR","2018","Args",":","output_dim","(","int",")",":","Output","dimension","bias","(","bool",")",":","Optional","bias","act","(","Callable","or","str",")",":","name","of","the","activation","function","to","use","(","must","be","a","Keras","activation","function",")",",","or","alternatively",",","a","TensorFlow","operation","."]
docstr: Calculates the output size for each input group.
  
  The results are stored in two variables:
      * self.included_weight_groups: if the corresponding entry is True then the input group
        is valid and should be used.
      * self.weight_sizes: the size of the output from this group.
  
  The AttentionalAggregator is implemented to not use the first (head node) group. This makes
  the implementation different from other aggregators.
  
  Args:
      input_shape (list of list of int): Shape of input tensors for self
          and neighbour features
docstr_tok: ["Calculates","the","output","size","for","each","input","group",".","The","results","are","stored","in","two","variables",":","*","self.included_weight_groups",":","if","the","corresponding","entry","is","True","then","the","input","group","is","valid","and","should","be","used",".","*","self.weight_sizes",":","the","size","of","the","output","from","this","group",".","The","AttentionalAggregator","is","implemented","to","not","use","the","first","(","head","node",")","group",".","This","makes","the","implementation","different","from","other","aggregators",".","Args",":","input_shape","(","list","of","list","of","int",")",":","Shape","of","input","tensors","for","self","and","neighbour","features"]
code: def calculate_group_sizes(self, input_shape):
      """
      Calculates the output size for each input group.
  
      The results are stored in two variables:
          * self.included_weight_groups: if the corresponding entry is True then the input group
            is valid and should be used.
          * self.weight_sizes: the size of the output from this group.
  
      The AttentionalAggregator is implemented to not use the first (head node) group. This makes
      the implementation different from other aggregators.
  
      Args:
          input_shape (list of list of int): Shape of input tensors for self
              and neighbour features
      """
      # If the neighbours are zero-dimensional for any of the shapes
      # in the input, do not use the input group in the model.
      # XXX Ignore batch size, since dim != 0 results in None!!
      self.included_weight_groups = [
          all(dim != 0 for dim in group_shape[1:])
          for group_shape in input_shape
      ]
  
      # The total number of enabled input groups
      num_groups = np.sum(self.included_weight_groups) - 1
  
      # We do not assign any features to the head node group, unless this is the only group.
      if num_groups == 0:
          weight_dims = [self.output_dim] + [0] * (len(input_shape) - 1)
  
      else:
          # Calculate the dimensionality of each group, and put remainder into the first group
          # with non-zero dimensions.
          group_output_dim = self.output_dim // num_groups
          remainder_dim = (
              self.output_dim - num_groups * group_output_dim
          )
          weight_dims = [0]
          for g in self.included_weight_groups[1:]:
              if g:
                  group_dim = group_output_dim + remainder_dim
                  remainder_dim = 0
              else:
                  group_dim = 0
              weight_dims.append(group_dim)
  
      self.weight_dims = weight_dims
  
imports: import warnings
  import numpy
  from tensorflow.keras.layers import Layer
  from tensorflow.keras import Input
  from tensorflow.keras import backend
  from tensorflow.keras.layers import Lambda, Dropout, Reshape, LeakyReLU
  from tensorflow.keras.utils import Sequence
  from tensorflow.keras import activations, initializers, constraints, regularizers
  from typing import List, Tuple, Callable, AnyStr, Union
  from ..mapper import GraphSAGENodeGenerator, GraphSAGELinkGenerator, DirectedGraphSAGENodeGenerator, DirectedGraphSAGELinkGenerator, NodeSequence, LinkSequence
  from .misc import deprecated_model_function
  from ..connector.neo4j.mapper import Neo4jGraphSAGENodeGenerator, Neo4jDirectedGraphSAGENodeGenerator
label_desc: Use image node_id 3 for calling the AttentionalAggregator obj's underlying member method code with example usage: obj.calculate_group_sizes(input_shape) without return types