1
2
3
4
5
6
7
8
9
10
11
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Pure-Rust implementation of the Neuromorphic Intermediate Representation (NIR).
//!
//! NIR is a framework-agnostic graph format for spiking neural networks
//! (analogous to ONNX for conventional nets). This crate provides a typed
//! in-memory graph model plus HDF5 `.nir` read/write that interoperates with
//! the Python reference implementation.
//!
//! # Status
//!
//! **v0.4 — developer experience**: a public load-inspect-save example makes
//! the HDF5 workflow executable end to end, on top of the v0.3 I/O and v0.2
//! graph model — the closed [`NirNode`] enum (wire-accurate type strings),
//! [`NirGraph`] with ordered nodes/edges, [`Tensor`] / metadata types, and
//! structured [`NirError`].
//!
//! I/O lives behind the opt-in **`hdf5`** feature because it links the native
//! libhdf5 library; the graph model itself has no system dependencies. See the
//! [`io`] module for the feature gate, the file layout, and the version-string
//! policy.
//!
//! The independent opt-in **`serde`** feature implements Serde traits for the
//! graph model. Formats such as JSON are useful for debugging and tests only:
//! they are not a stable NIR schema or an interchange format. Use HDF5 `.nir`
//! through [`io::read`] / [`io::write`] for interoperability. JSON also cannot
//! represent non-finite floats faithfully, so NaN and infinities are not
//! guaranteed to round-trip.
//!
//! ```toml
//! nir-rs = { version = "0.4", features = ["hdf5"] }
//! ```
//!
//! Run the complete fixture workflow from a checkout with:
//!
//! ```text
//! cargo run --example load_inspect_lif --features hdf5
//! ```
//!
//! # Example
//!
//! ```
//! use nir_rs::nodes::{Affine, Input, Lif, Output};
//! use nir_rs::types::Tensor;
//! use nir_rs::{NirGraph, NirNode};
//!
//! let mut g = NirGraph::new();
//! g.insert_node(
//! "input",
//! NirNode::Input(Input {
//! shape: vec![4],
//! metadata: Default::default(),
//! }),
//! )?;
//! g.insert_node(
//! "fc",
//! NirNode::Affine(Affine {
//! weight: Tensor::from_f32(vec![2, 4], vec![0.1; 8])?,
//! bias: Tensor::from_f32(vec![2], vec![0.0, 0.0])?,
//! metadata: Default::default(),
//! }),
//! )?;
//! g.insert_node(
//! "lif",
//! NirNode::Lif(Lif {
//! tau: Tensor::from_f64(vec![2], vec![10.0, 10.0])?,
//! r: Tensor::from_f64(vec![2], vec![1.0, 1.0])?,
//! v_leak: Tensor::from_f64(vec![2], vec![0.0, 0.0])?,
//! v_threshold: Tensor::from_f64(vec![2], vec![1.0, 1.0])?,
//! v_reset: None,
//! metadata: Default::default(),
//! }),
//! )?;
//! g.insert_node(
//! "output",
//! NirNode::Output(Output {
//! shape: vec![2],
//! metadata: Default::default(),
//! }),
//! )?;
//! g.add_edge("input", "fc");
//! g.add_edge("fc", "lif");
//! g.add_edge("lif", "output");
//! g.validate_structure()?;
//!
//! // With `features = ["hdf5"]`, the graph exchanges as a `.nir` file:
//! // nir_rs::io::write("model.nir", &g)?;
//! // let reloaded = nir_rs::io::read("model.nir")?;
//! # Ok::<(), nir_rs::NirError>(())
//! ```
//!
//! # Non-goals
//!
//! - SNN training or simulation
//! - Mapping graphs onto specific neuromorphic hardware
//! - Framework-specific converters (belong in producer/consumer tools)
//!
//! # Upstream
//!
//! - [neuromorphs/NIR](https://github.com/neuromorphs/NIR)
//! - [neuroir.org](https://neuroir.org/)
//! - Paper: [Pedersen et al., Nat. Commun. 15, 8122 (2024)](https://doi.org/10.1038/s41467-024-52259-9)
//! — please cite if you use NIR (see the repository `README` / `CITATION.cff`)
//!
//! Wire type names must match the Python IR (`CubaLIF`, `Conv2d`, …), not
//! informal marketing aliases.
pub use ;
pub use NirGraph;
pub use NirNode;
pub use ;