Skip to main content

rsnn_eta/
lib.rs

1//! # rsnn-eta
2//!
3//! A biologically-inspired ETA estimator using a Recurrent Spiking Neural Network (RSNN)
4//! with Spike-Timing-Dependent Plasticity (STDP) to learn correction factors for
5//! time-remaining predictions.
6//!
7//! The core idea: a pluggable base estimator (default: exponential moving average) provides
8//! a naive ETA, and an RSNN learns a correction factor from prediction errors. The network
9//! adapts online via STDP, detecting phase transitions, bursts, and non-linear progress
10//! patterns that defeat simple smoothing.
11//!
12//! ## Quick start
13//!
14//! ```rust
15//! use std::time::{Duration, Instant};
16//! use rsnn_eta::RsnnEta;
17//!
18//! let mut eta = RsnnEta::new();
19//! let start = Instant::now();
20//!
21//! for i in 1..=100 {
22//!     let elapsed = Duration::from_millis(i * 50);
23//!     if let Some(remaining) = eta.tick(i * 10, 10_000, elapsed, start + elapsed) {
24//!         // `remaining` is the corrected ETA as a Duration
25//!     }
26//! }
27//! ```
28//!
29//! ## Builder
30//!
31//! ```rust
32//! use rsnn_eta::RsnnEta;
33//!
34//! let mut eta = RsnnEta::builder()
35//!     .neurons(100)          // reservoir size (default: 50)
36//!     .steps_per_tick(30)    // simulation steps per tick (default: 20)
37//!     .burn_in_ticks(15)     // ticks before STDP learning starts (default: 10)
38//!     .ema_alpha(0.03)       // base EMA smoothing (default: 0.05)
39//!     .seed(123)             // RNG seed for reproducibility
40//!     .persistence("./weights.bin")  // optional save/load path
41//!     .build();
42//! ```
43//!
44//! ## Custom base estimator
45//!
46//! ```rust
47//! use std::time::Duration;
48//! use rsnn_eta::BaseEstimator;
49//!
50//! struct MyEstimator { /* ... */ }
51//!
52//! impl BaseEstimator for MyEstimator {
53//!     fn update(&mut self, position: u64, length: u64, elapsed: Duration) { /* ... */ }
54//!     fn estimate(&self) -> Option<Duration> { None }
55//!     fn is_warm(&self) -> bool { false }
56//!     fn reset(&mut self) {}
57//!     fn steps_per_sec(&self) -> f64 { 0.0 }
58//!     fn clone_box(&self) -> Box<dyn BaseEstimator> { Box::new(MyEstimator {}) }
59//! }
60//!
61//! let eta = rsnn_eta::RsnnEta::builder()
62//!     .base_estimator(Box::new(MyEstimator {}))
63//!     .build();
64//! ```
65//!
66//! ## Side-channel signals
67//!
68//! Inject additional features (e.g., batch size, phase indicator) beyond what the
69//! progress bar exposes:
70//!
71//! ```rust
72//! let (mut eta, tx) = rsnn_eta::RsnnEta::builder().build_with_signals();
73//! tx.send(vec![0.8, 1.2]).unwrap(); // e.g., batch_size_ratio, phase_indicator
74//! ```
75//!
76//! ## Architecture
77//!
78//! ```text
79//! tick(pos, len, elapsed, now)
80//!   │
81//!   ├─► Base Estimator (EMA) ──► base_eta
82//!   │
83//!   ├─► Encoder (rate + temporal coding)
84//!   │     │
85//!   │     ▼
86//!   │   RSNN Reservoir (LIF neurons, sparse E/I, STDP)
87//!   │     │
88//!   │     ▼
89//!   │   Decoder ──► correction_factor
90//!   │
91//!   └─► final_eta = base_eta × (confidence × factor + (1-confidence) × 1.0)
92//! ```
93
94pub mod config;
95pub mod lif;
96pub mod network;
97pub mod stdp;
98pub mod encoder;
99pub mod decoder;
100pub mod estimator;
101pub mod tracker;
102pub mod builder;
103pub mod persistence;
104
105pub use builder::{RsnnEta, RsnnEtaBuilder};
106pub use estimator::{BaseEstimator, EmaEstimator};
107pub use config::{NetworkConfig, StdpConfig, DecoderConfig};