athena__kipf_msgpass_layer Module

Module implementing Kipf & Welling Graph Convolutional Network (GCN)

This module implements the graph convolutional layer from Kipf & Welling (2017) with symmetric degree normalisation for semi-supervised learning.

Mathematical operation:

where: * (adjacency matrix with added self-loops) * is the degree matrix of * is the node feature matrix at layer l * is a learnable weight matrix * is the activation function

The normalisation ensures proper scaling by degree. Preserves graph structure, producing node-level (not graph-level) outputs.

Reference: Kipf & Welling (2017), ICLR



Interfaces

public interface kipf_msgpass_layer_type

Interface for setting up the MPNN layer

  • private module function layer_setup(num_vertex_features, num_time_steps, activation, kernel_initialiser, verbose) result(layer)

    Set up the message passing layer

    Arguments

    Type IntentOptional Attributes Name
    integer, intent(in), dimension(:) :: num_vertex_features

    Number of features

    integer, intent(in) :: num_time_steps

    Number of time steps

    class(*), intent(in), optional :: activation

    Activation function and kernel initialiser

    class(*), intent(in), optional :: kernel_initialiser

    Activation function and kernel initialiser

    integer, intent(in), optional :: verbose

    Verbosity level

    Return Value type(kipf_msgpass_layer_type)

    Instance of the message passing layer


Derived Types

type, public, extends(msgpass_layer_type) ::  kipf_msgpass_layer_type

Components

Type Visibility Attributes Name Initial
class(base_actv_type), public, allocatable :: activation

Activation function

class(base_init_type), public, allocatable :: bias_init

Initialisers for kernel and bias

character(len=14), public :: bias_initialiser = ''

Initialisers for kernel and bias

integer, public, allocatable, dimension(:) :: bias_shape

Shape of biases

type(graph_type), public, allocatable, dimension(:) :: graph

Graph structure of input data

integer, public :: id

Unique identifier

logical, public :: inference = .false.

Inference mode

integer, public :: input_rank = 0

Rank of input data

integer, public, allocatable, dimension(:) :: input_shape

Input shape

class(base_init_type), public, allocatable :: kernel_init

Initialisers for kernel and bias

character(len=14), public :: kernel_initialiser = ''

Initialisers for kernel and bias

character(len=:), public, allocatable :: name

Layer name

integer, public, dimension(:), allocatable :: num_edge_features

Number of edge features for each time step

integer, public :: num_output_edge_features

Number of output edge features

integer, public :: num_output_vertex_features

Number of output vertex features

integer, public :: num_outputs

Number of outputs (if output is not graph structure)

integer, public :: num_params = 0

Number of learnable parameters

integer, public, dimension(:), allocatable :: num_params_msg

Number of learnable parameters for each message

integer, public :: num_params_readout

Number of learnable parameters for the readout

integer, public :: num_time_steps

Number of time steps

integer, public, dimension(:), allocatable :: num_vertex_features

Number of vertex features for each time step

class(array_type), public, allocatable, dimension(:,:) :: output

Output

integer, public :: output_rank = 0

Rank of output data

integer, public, allocatable, dimension(:) :: output_shape

Output shape

type(array_type), public, allocatable, dimension(:) :: params

Learnable parameters

character(len=20), public :: subtype = repeat(" ", 20)
character(len=4), public :: type = 'base'

Layer type

logical, public :: use_bias = .false.

Layer has bias

logical, public :: use_graph_input = .false.

Use graph input

logical, public :: use_graph_output = .false.

Use graph output

integer, public, allocatable, dimension(:,:) :: weight_shape

Shape of weights

Constructor

Interface for setting up the MPNN layer

private module function layer_setup (num_vertex_features, num_time_steps, activation, kernel_initialiser, verbose)

Set up the message passing layer

Type-Bound Procedures

procedure, public :: add_t_t => add_learnable

Add two layers

procedure, public, pass(this) :: build_from_onnx => build_from_onnx_base

Build layer from ONNX node and initialiser

procedure, public, pass(this) :: emit_onnx_graph_inputs => emit_onnx_graph_inputs_base

Emit graph input tensor declarations for this layer

procedure, public, pass(this) :: emit_onnx_nodes => emit_onnx_nodes_kipf

Emit ONNX JSON nodes for Kipf GCN layer

procedure, public, pass(this) :: extract_output => extract_output_base

Extract the output of the layer as a standard real array

procedure, public, pass(this) :: forward => forward_msgpass

Forward pass for message passing layer

procedure, public, pass(this) :: forward_eval => forward_eval_base

Forward pass of layer and return output for evaluation

procedure, public, pass(this) :: get_attributes => get_attributes_kipf

Get the attributes of the layer (for ONNX export)

procedure, public, pass(this) :: get_gradients

Get parameter gradients of layer

procedure, public, pass(this) :: get_num_params => get_num_params_kipf

Get the number of parameters for the message passing layer

procedure, public, pass(this) :: get_params

Get learnable parameters of layer

procedure, public, pass(this) :: init => init_kipf

Initialise the message passing layer

procedure, public, pass(this) :: nullify_graph => nullify_graph_base

Nullify the forward pass data of the layer to free memory

Read more…
generic, public :: operator(+) => add_t_t

Operator overloading for addition

procedure, public, pass(this) :: print => print_base

Print the layer to a file with additional information

procedure, public, pass(this) :: print_to_unit => print_to_unit_kipf

Print the message passing layer

procedure, public, pass(this) :: read => read_kipf

Read the message passing layer

procedure, public, pass(this) :: reduce => reduce_learnable

Merge another learnable layer into this one

procedure, public, pass(this) :: set_gradients

Set learnable parameters of layer

procedure, public, pass(this) :: set_graph => set_graph_msgpass
procedure, public, pass(this) :: set_hyperparams => set_hyperparams_kipf

Set the hyperparameters for the message passing layer

procedure, public, pass(this) :: set_params

Set learnable parameters of layer

procedure, public, pass(this) :: set_rank => set_rank_base

Set the input and output ranks of the layer

procedure, public, pass(this) :: set_shape => set_shape_base

Set the input shape of the layer

procedure, public, pass(this) :: update_message => update_message_kipf

Update the message

procedure, public, pass(this) :: update_readout => update_readout_kipf

Update the readout


Functions

public function read_kipf_msgpass_layer(unit, verbose) result(layer)

Read kipf message passing layer from file and return layer

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: unit

Unit number

integer, intent(in), optional :: verbose

Verbosity level

Return Value class(base_layer_type), allocatable

Instance of the message passing layer

private function get_attributes_kipf(this) result(attributes)

Get the attributes of the Kipf GCN layer (for ONNX export)

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(in) :: this

Instance of the message passing layer

Return Value type(onnx_attribute_type), allocatable, dimension(:)

Attributes for ONNX export

private pure function get_num_params_kipf(this) result(num_params)

Get the number of parameters for the message passing layer

Read more…

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(in) :: this

Instance of the message passing layer

Return Value integer

Number of parameters

private module function layer_setup(num_vertex_features, num_time_steps, activation, kernel_initialiser, verbose) result(layer)

Set up the message passing layer

Arguments

Type IntentOptional Attributes Name
integer, intent(in), dimension(:) :: num_vertex_features

Number of features

integer, intent(in) :: num_time_steps

Number of time steps

class(*), intent(in), optional :: activation

Activation function and kernel initialiser

class(*), intent(in), optional :: kernel_initialiser

Activation function and kernel initialiser

integer, intent(in), optional :: verbose

Verbosity level

Return Value type(kipf_msgpass_layer_type)

Instance of the message passing layer


Subroutines

private subroutine emit_kipf_timestep(prefix, t, nv_in, nv_out, weight_data, activation_name, nodes, num_nodes, max_nodes, inits, num_inits, max_inits, vertex_out)

Emit ONNX nodes for one Kipf GCN time step.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: prefix
integer, intent(in) :: t
integer, intent(in) :: nv_in
integer, intent(in) :: nv_out
real(kind=real32), intent(in) :: weight_data(:)
character(len=*), intent(in) :: activation_name
type(onnx_node_type), intent(inout), dimension(:) :: nodes
integer, intent(inout) :: num_nodes
integer, intent(in) :: max_nodes
type(onnx_initialiser_type), intent(inout), dimension(:) :: inits
integer, intent(inout) :: num_inits
integer, intent(in) :: max_inits
character(len=128), intent(out) :: vertex_out

private subroutine emit_onnx_nodes_kipf(this, prefix, nodes, num_nodes, max_nodes, inits, num_inits, max_inits, input_name, is_last_layer, format)

Emit ONNX JSON nodes for Kipf GCN layer

Read more…

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(in) :: this

Instance of the layer

character(len=*), intent(in) :: prefix

Node name prefix (e.g. "node_2")

type(onnx_node_type), intent(inout), dimension(:) :: nodes

Accumulator for ONNX nodes

integer, intent(inout) :: num_nodes

Current number of nodes

integer, intent(in) :: max_nodes

Maximum capacity

type(onnx_initialiser_type), intent(inout), dimension(:) :: inits

Accumulator for ONNX initialisers

integer, intent(inout) :: num_inits

Current number of initialisers

integer, intent(in) :: max_inits

Maximum capacity

character(len=*), intent(in), optional :: input_name

Unused sequential input name

logical, intent(in), optional :: is_last_layer

Unused last-layer flag

integer, intent(in), optional :: format

Unused export format selector

private subroutine init_kipf(this, input_shape, verbose)

Initialise the message passing layer

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(inout) :: this

Instance of the fully connected layer

integer, intent(in), dimension(:) :: input_shape

Input shape

integer, intent(in), optional :: verbose

Verbosity level

private subroutine print_to_unit_kipf(this, unit)

Print kipf message passing layer to unit

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(in) :: this

Instance of the message passing layer

integer, intent(in) :: unit

File unit

private subroutine read_kipf(this, unit, verbose)

Read the message passing layer

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(inout) :: this

Instance of the message passing layer

integer, intent(in) :: unit

Unit to read from

integer, intent(in), optional :: verbose

Verbosity level

private subroutine set_hyperparams_kipf(this, num_vertex_features, num_time_steps, activation, kernel_initialiser, verbose)

Set the hyperparameters for the message passing layer

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(inout) :: this

Instance of the message passing layer

integer, intent(in), dimension(:) :: num_vertex_features

Number of vertex features

integer, intent(in) :: num_time_steps

Number of time steps

class(base_actv_type), intent(in), allocatable :: activation

Activation function

class(base_init_type), intent(in), allocatable :: kernel_initialiser

Kernel initialiser

integer, intent(in), optional :: verbose

Verbosity level

private subroutine update_message_kipf(this, input)

Update the message

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(inout), target :: this

Instance of the message passing layer

class(array_type), intent(in), dimension(:,:), target :: input

Input to the message passing layer

private subroutine update_readout_kipf(this)

Update the readout (empty for node-level output)

Arguments

Type IntentOptional Attributes Name
class(kipf_msgpass_layer_type), intent(inout), target :: this

Instance of the message passing layer