code: def __init__(
      self,
      input_state_dimension: int,
      output_state_dimension: int,
      message_dimension: int,
      num_edge_types: int,
      message_aggregation_function: Union[
          str, AbstractMessageAggregation
      ],
      message_activation: Optional[nn.Module] = nn.GELU(),
      use_target_state_as_message_input: bool = True,
      mlp_hidden_layers: Union[List[int], int] = 0,
      use_layer_norm: bool = True,
      use_dense_layer: bool = True,
      dropout_rate: float = 0.0,
      dense_activation: Optional[nn.Module] = nn.Tanh(),
      features_dimension: int = 0,
  ):
      super().__init__()
      self.__input_state_dim = input_state_dimension
      self.__use_target_state_as_message_input = (
          use_target_state_as_message_input
      )
      self.__output_state_dim = output_state_dimension
  
      if use_target_state_as_message_input:
          message_input_size = 2 * input_state_dimension
      else:
          message_input_size = input_state_dimension
      self.__edge_message_transformation_layers = nn.ModuleList(
          [
              MLP(
                  input_dimension=message_input_size
                  + features_dimension,
                  output_dimension=message_dimension,
                  hidden_layers=mlp_hidden_layers,
              )
              for _ in range(num_edge_types)
          ]
      )
      self.__aggregation_fn = message_aggregation_function
      if isinstance(message_aggregation_function, str):
          aggregated_state_size = message_dimension
      else:
          aggregated_state_size = (
              self.__aggregation_fn.output_state_size(message_dimension)
          )
  
      self.__message_activation = message_activation
  
      state_update_layers: List[nn.Module] = []
      if use_layer_norm:
          state_update_layers.append(
              nn.LayerNorm(aggregated_state_size)
          )
      if use_dense_layer:
          state_update_layers.append(
              nn.Linear(aggregated_state_size, output_state_dimension)
          )
          nn.init.xavier_uniform_(state_update_layers[-1].weight)
          if dense_activation is not None:
              state_update_layers.append(dense_activation)
      state_update_layers.append(nn.Dropout(p=dropout_rate))
  
      self.__state_update = nn.Sequential(*state_update_layers)
  
file_path: ptgnn/ptgnn/neuralmodels/gnn/messagepassing/mlpmessagepassing.py
imports: import torch
  from torch import nn
  from typing import Callable, Dict, List, Optional, Tuple, Union
  from ptgnn.neuralmodels.gnn.messagepassing.abstractmessagepassing import AbstractMessageAggregation, AbstractMessagePassingLayer
  from ptgnn.neuralmodels.mlp import MLP
label_desc: Use image node_id 1 to create a new MlpMessagePassingLayer object from inherited base classes: AbstractMessagePassingLayer with example: obj = MlpMessagePassingLayer(input_state_dimension, output_state_dimension, message_dimension, num_edge_types, message_aggregation_function, message_activation, use_target_state_as_message_input, mlp_hidden_layers, use_layer_norm, use_dense_layer, dropout_rate, dense_activation, features_dimension)