class_docstr: A XENet convolutional layer from the paper
  
    > [XENet: Using a new graph convolution to accelerate the timeline for protein design on quantum computers](https://www.biorxiv.org/content/10.1101/2021.05.05.442729v1)<br>
    > Jack B. Maguire, Daniele Grattarola, Eugene Klyshko, Vikram Khipple Mulligan, Hans Melo
  
  **Mode**: single, disjoint, mixed.
  
  **This layer expects a sparse adjacency matrix.**
  
  For a version of this layer that supports batch mode, you can use
  `spektral.layers.XENetDenseConv` as a drop-in replacement.
  
  This layer computes for each node \(i\):
  $$
      \s_{ij} = \text{PReLU} \left( (\x_{i} \| \x_{j} \| \e_{ij} \| \e_{ji}) \W^{(s)} + \b^{(s)} \right) \\
      \s^{(\text{out})}_{i} = \sum\limits_{j \in \mathcal{N}(i)} \s_{ij} \\
      \s^{(\text{in})}_{i} = \sum\limits_{j \in \mathcal{N}(i)} \s_{ji} \\
      \x_{i}' = \sigma\left( (\x_{i} \| \s^{(\text{out})}_{i} \| \s^{(\text{in})}_{i}) \W^{(n)} + \b^{(n)} \right) \\
      \e_{ij}' = \sigma\left( \s_{ij} \W^{(e)} + \b^{(e)} \right)
  $$
  
  **Input**
  
  - Node features of shape `([batch], n_nodes, n_node_features)`;
  - Binary adjacency matrices of shape `([batch], n_nodes, n_nodes)`;
  - Edge features of shape `(num_edges, n_edge_features)`;
  
  **Output**
  
  - Node features with the same shape of the input, but the last dimension
  changed to `node_channels`.
  - Edge features with the same shape of the input, but the last dimension
  changed to `edge_channels`.
  
  **Arguments**
  
  - `stack_channels`: integer or list of integers, number of channels for the hidden layers;
  - `node_channels`: integer, number of output channels for the nodes;
  - `edge_channels`: integer, number of output channels for the edges;
  - `attention`: whether to use attention when aggregating the stacks;
  - `node_activation`: activation function for nodes;
  - `edge_activation`: activation function for edges;
  - `use_bias`: bool, add a bias vector to the output;
  - `kernel_initializer`: initializer for the weights;
  - `bias_initializer`: initializer for the bias vector;
  - `kernel_regularizer`: regularization applied to the weights;
  - `bias_regularizer`: regularization applied to the bias vector;
  - `activity_regularizer`: regularization applied to the output;
  - `kernel_constraint`: constraint applied to the weights;
  - `bias_constraint`: constraint applied to the bias vector.
class_docstr_tok: ["A","XENet","convolutional","layer","from","the","paper",">","[","XENet",":","Using","a","new","graph","convolution","to","accelerate","the","timeline","for","protein","design","on","quantum","computers","]","(","https",":","\/\/www.biorxiv.org\/content\/10.1101\/2021.05.05.442729v1",")","<","br",">",">","Jack","B.","Maguire",",","Daniele","Grattarola",",","Eugene","Klyshko",",","Vikram","Khipple","Mulligan",",","Hans","Melo","*","*","Mode","*","*",":","single",",","disjoint",",","mixed",".","*","*","This","layer","expects","a","sparse","adjacency","matrix",".","*","*","For","a","version","of","this","layer","that","supports","batch","mode",",","you","can","use","`","spektral.layers.XENetDenseConv","`","as","a","drop-in","replacement",".","This","layer","computes","for","each","node","\\","(","i\\",")",":","$","$","\\s_","{","ij","}","=","\\text","{","PReLU","}","\\left","(","(","\\x_","{","i","}","\\|","\\x_","{","j","}","\\|","\\e_","{","ij","}","\\|","\\e_","{","ji","}",")","\\W^","{","(","s",")","}","+","\\b^","{","(","s",")","}","\\right",")","\\\\","\\s^","{","(","\\text","{","out","}",")","}","_","{","i","}","=","\\sum\\limits_","{","j","\\in","\\mathcal","{","N","}","(","i",")","}","\\s_","{","ij","}","\\\\","\\s^","{","(","\\text","{","in","}",")","}","_","{","i","}","=","\\sum\\limits_","{","j","\\in","\\mathcal","{","N","}","(","i",")","}","\\s_","{","ji","}","\\\\","\\x_","{","i","}","'","=","\\sigma\\left","(","(","\\x_","{","i","}","\\|","\\s^","{","(","\\text","{","out","}",")","}","_","{","i","}","\\|","\\s^","{","(","\\text","{","in","}",")","}","_","{","i","}",")","\\W^","{","(","n",")","}","+","\\b^","{","(","n",")","}","\\right",")","\\\\","\\e_","{","ij","}","'","=","\\sigma\\left","(","\\s_","{","ij","}","\\W^","{","(","e",")","}","+","\\b^","{","(","e",")","}","\\right",")","$","$","*","*","Input","*","*","-","Node","features","of","shape","`","(","[","batch","]",",","n_nodes",",","n_node_features",")","`",";","-","Binary","adjacency","matrices","of","shape","`","(","[","batch","]",",","n_nodes",",","n_nodes",")","`",";","-","Edge","features","of","shape","`","(","num_edges",",","n_edge_features",")","`",";","*","*","Output","*","*","-","Node","features","with","the","same","shape","of","the","input",",","but","the","last","dimension","changed","to","`","node_channels","`",".","-","Edge","features","with","the","same","shape","of","the","input",",","but","the","last","dimension","changed","to","`","edge_channels","`",".","*","*","Arguments","*","*","-","`","stack_channels","`",":","integer","or","list","of","integers",",","number","of","channels","for","the","hidden","layers",";","-","`","node_channels","`",":","integer",",","number","of","output","channels","for","the","nodes",";","-","`","edge_channels","`",":","integer",",","number","of","output","channels","for","the","edges",";","-","`","attention","`",":","whether","to","use","attention","when","aggregating","the","stacks",";","-","`","node_activation","`",":","activation","function","for","nodes",";","-","`","edge_activation","`",":","activation","function","for","edges",";","-","`","use_bias","`",":","bool",",","add","a","bias","vector","to","the","output",";","-","`","kernel_initializer","`",":","initializer","for","the","weights",";","-","`","bias_initializer","`",":","initializer","for","the","bias","vector",";","-","`","kernel_regularizer","`",":","regularization","applied","to","the","weights",";","-","`","bias_regularizer","`",":","regularization","applied","to","the","bias","vector",";","-","`","activity_regularizer","`",":","regularization","applied","to","the","output",";","-","`","kernel_constraint","`",":","constraint","applied","to","the","weights",";","-","`","bias_constraint","`",":","constraint","applied","to","the","bias","vector","."]
code: def build(self, input_shape):
      assert len(input_shape) == 3  # X, A, E, right?
      layer_kwargs = dict(
          kernel_initializer=self.kernel_initializer,
          bias_initializer=self.bias_initializer,
          kernel_regularizer=self.kernel_regularizer,
          bias_regularizer=self.bias_regularizer,
          kernel_constraint=self.kernel_constraint,
          bias_constraint=self.bias_constraint,
      )
  
      self.stack_models = []
      self.stack_model_acts = []
  
      if isinstance(self.stack_channels, Iterable):
          assert len(self.stack_channels) > 0
  
          for count, value in enumerate(self.stack_channels):
              self.stack_models.append(Dense(value, **layer_kwargs))
              if count != len(self.stack_channels) - 1:
                  self.stack_model_acts.append(ReLU())
              else:
                  self.stack_model_acts.append(PReLU())
      else:
          self.stack_models.append(
              Dense(self.stack_channels, **layer_kwargs)
          )
          self.stack_model_acts.append(PReLU())
  
      self.node_model = Dense(
          self.node_channels,
          activation=self.node_activation,
          **layer_kwargs,
      )
      self.edge_model = Dense(
          self.edge_channels,
          activation=self.edge_activation,
          **layer_kwargs,
      )
  
      if self.attention:
          self.incoming_att_sigmoid = Dense(1, activation="sigmoid")
          self.incoming_att_multiply = Multiply()
          self.outgoing_att_sigmoid = Dense(1, activation="sigmoid")
          self.outgoing_att_multiply = Multiply()
  
      self.built = True
  
imports: from collections.abc import Iterable
  import tensorflow
  from tensorflow.keras.layers import Concatenate, Dense, Multiply, PReLU, ReLU
  from tensorflow.python.ops import gen_sparse_ops
  from spektral.layers.convolutional.conv import Conv
  from spektral.layers.convolutional.message_passing import MessagePassing
label_desc: Use image node_id 2 for calling the XENetConv obj's underlying member method code with example usage: obj.build(input_shape) without return types