Skip to content

Graphs

Event-based graph neural network layer for spike-graph message passing.

  • StochasticGraphLayer — GNN convolution where message passing happens via bitstreams. Takes adjacency matrix + per-node feature vectors, propagates through graph structure with SC arithmetic. Supports variable-topology graphs.
import numpy as np
from sc_neurocore.graphs import StochasticGraphLayer

adj = (np.random.rand(20, 20) > 0.7).astype(float)
np.fill_diagonal(adj, 0)
layer = StochasticGraphLayer(adj_matrix=adj, n_features=16)
features = np.random.rand(20, 16)
output = layer.forward(features)

sc_neurocore.graphs.gnn

StochasticGraphLayer

Event-Based Graph Convolution Layer. Message Passing happens via Bitstreams.

Source code in src/sc_neurocore/graphs/gnn.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class StochasticGraphLayer:
    """
    Event-Based Graph Convolution Layer.
    Message Passing happens via Bitstreams.
    """

    def __init__(self, adj_matrix: np.ndarray[Any, Any], n_features: int):
        self.adj = adj_matrix  # (N, N)
        self.n_nodes = adj_matrix.shape[0]
        self.n_features = n_features
        # Weights: (Features, Features) - simple linear transform
        self.weights = np.random.uniform(0, 1, (n_features, n_features))

    def forward(self, node_features: np.ndarray[Any, Any]) -> np.ndarray[Any, Any]:
        """
        node_features: (N, Features)
        """
        output = np.zeros_like(node_features)

        # 1. Message Passing (Aggregation)
        # For each node, sum neighbor features
        # In SC, this is MUX aggregation

        # Standard GCN: A * X * W

        # Aggregation:
        agg_features = np.dot(self.adj, node_features)
        # Normalize by degree? (Simplified)
        degrees = np.sum(self.adj, axis=1, keepdims=True)
        degrees[degrees == 0] = 1
        agg_features /= degrees

        # 2. Transformation (Linear)
        # Out = Agg * W
        output = np.dot(agg_features, self.weights)

        # 3. Non-linearity (Tanh/Sigmoid)
        return np.tanh(output)

forward(node_features)

node_features: (N, Features)

Source code in src/sc_neurocore/graphs/gnn.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def forward(self, node_features: np.ndarray[Any, Any]) -> np.ndarray[Any, Any]:
    """
    node_features: (N, Features)
    """
    output = np.zeros_like(node_features)

    # 1. Message Passing (Aggregation)
    # For each node, sum neighbor features
    # In SC, this is MUX aggregation

    # Standard GCN: A * X * W

    # Aggregation:
    agg_features = np.dot(self.adj, node_features)
    # Normalize by degree? (Simplified)
    degrees = np.sum(self.adj, axis=1, keepdims=True)
    degrees[degrees == 0] = 1
    agg_features /= degrees

    # 2. Transformation (Linear)
    # Out = Agg * W
    output = np.dot(agg_features, self.weights)

    # 3. Non-linearity (Tanh/Sigmoid)
    return np.tanh(output)