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};