Skip to content

2 Core Graph Model

Raul Cardenas Montoya edited this page Sep 19, 2026 · 1 revision

Core Graph Model

Relevant source files

The following files were used as context for generating this wiki page:

The nir-rs crate provides a typed, in-memory representation of the Neuromorphic Intermediate Representation (NIR). This model is designed for high-fidelity interoperability with the Python reference implementation while leveraging Rust's type system to enforce structural and data invariants.

The core model consists of four primary components:

  1. NirGraph: The top-level container for nodes and edges.
  2. NirNode: An enum representing specific computational primitives (e.g., Lif, Conv2d).
  3. Tensor: A multi-dimensional array type for weights and parameters.
  4. MetadataMap: A flexible dictionary for storing auxiliary information.

Code Entity Mapping

The following diagram illustrates the relationship between the logical neuromorphic concepts and the specific Rust entities defined in the codebase.

Diagram: Logical to Code Entity Mapping

graph TD
    subgraph "Natural Language Space"
        A["Neural Network"]
        B["Neuron / Layer"]
        C["Synaptic Weight"]
        D["Connection"]
        E["Extra Info"]
    end

    subgraph "Code Entity Space"
        A_C["NirGraph"]
        B_C["NirNode"]
        C_C["Tensor"]
        D_C["edges: Vec<(String, String)>"]
        E_C["MetadataMap"]
    end

    A -- "represented by" --> A_C
    B -- "represented by" --> B_C
    C -- "stored in" --> C_C
    D -- "defined by" --> D_C
    E -- "mapped to" --> E_C

    A_C -->|"contains"| B_C
    A_C -->|"contains"| D_C
    B_C -->|"parameters"| C_C
    B_C -->|"annotated by"| E_C
Loading

Sources: src/lib.rs:42-84, src/graph.rs:23-32, src/nodes.rs:55-113, src/types.rs:105-110


NirGraph: Graph Container and Validation

The NirGraph struct is the primary entry point for building or loading a NIR model. It manages a collection of named nodes using an IndexMap to ensure that iteration and serialization order remain stable, which is critical for debugging and file comparisons.

Key features include:

  • Edge Management: Edges are stored as simple pairs of strings (source_name, destination_name) src/graph.rs:30-31.
  • Validation: The validate_structure method ensures that all edge endpoints exist, that no duplicate edges are present, and that nested subgraphs conform to depth limits (MAX_NESTING_DEPTH = 1024) src/graph.rs:100-128.
  • Recursion: NIR supports nested subgraphs via the NirNode::Graph variant, allowing for hierarchical model definitions.

For details, see NirGraph: Graph Container and Validation.

Sources: src/graph.rs:16-32, src/graph.rs:100-128


NirNode: Neuromorphic Primitives

Computational logic in NIR is encapsulated in the NirNode enum. This is a "closed" enum, meaning it mirrors the exact wire-type strings used by the Python implementation (e.g., CubaLIF, Affine, Threshold).

  • Variants: Includes linear operations (Linear, Affine), activations (Threshold), and various neuron models (Lif, CubaLI, If).
  • Fields: Each variant contains specific parameters (as Tensor objects) and a MetadataMap.
  • Naming: Field names use snake_case to match the Python dataclass definitions, ensuring seamless serialization.

For details, see NirNode: Neuromorphic Primitives.

Sources: src/nodes.rs:5-11, src/nodes.rs:55-113, src/nodes.rs:118-140


Tensor and Type System

The Tensor struct represents dense, row-major (C-order) multi-dimensional arrays. To maintain data integrity, Tensor fields are private; they can only be constructed through methods that verify the shape product == data.len() invariant.

Diagram: Tensor Data Hierarchy

graph TD
    subgraph "Tensor Struct"
        T["Tensor"] --> S["shape: Vec<usize>"]
        T --> D["data: TensorData"]
    end

    subgraph "TensorData Enum"
        D --> F32["F32(Vec<f32>)"]
        D --> F64["F64(Vec<f64>)"]
        D --> I64["I64(Vec<i64>)"]
        D --> B["Bool(Vec<bool>)"]
    end

    subgraph "DType Enum"
        DT["DType"]
        DT --- DT_F32["F32"]
        DT --- DT_F64["F64"]
        DT --- DT_I64["I64"]
        DT --- DT_B["Bool"]
    end

    D -. "identifies as" .-> DT
Loading

Sources: src/types.rs:15-24, src/types.rs:42-51, src/types.rs:105-110, src/types.rs:153-157

The type system supports F32, F64, I64, and Bool data types. Metadata is handled via MetadataMap (a HashMap<String, MetadataValue>), which supports scalars, strings, and nested maps.

For details, see Tensor and Type System.


Structural and Parameter Validation

Beyond basic graph connectivity, validation encompasses heap-allocated work-list traversals for nested subgraphs to prevent stack overflow, deterministic error ordering, and an opt-in parameter validation pass (validate_parameters) that checks convolution and pooling invariants.

For details, see Structural and Parameter Validation.

Sources: src/graph.rs:100-144


Error Handling

The library uses a structured NirError enum to categorize failures. This ensures that users can programmatically distinguish between I/O errors, validation failures, and unsupported features.

Common error categories:

  • Graph Errors: DuplicateNode, MissingNode, DuplicateEdge, InvalidGraph.
  • Data Errors: InvalidTensor (shape mismatch), UnknownNodeType.
  • I/O Errors: Io, UnsupportedVersion, ReadLimitExceeded.

For details, see Error Handling.

Sources: src/error.rs:10-40

Clone this wiki locally