Skip to main content

limbic_critic/
modulators.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Neuromodulator concentrations produced by a critic.
4//!
5//! A [`ModulatorVector`] is the primary output of
6//! [`SimpleCritic::assess`](crate::SimpleCritic::assess) /
7//! [`try_assess`](crate::SimpleCritic::try_assess) and
8//! [`TDCritic::assess`](crate::TDCritic::assess) /
9//! [`try_assess`](crate::TDCritic::try_assess). Each field maps to a
10//! classical neuromodulator role used for reward-modulated learning and
11//! plasticity control in SNN systems.
12//!
13//! # Example
14//!
15//! ```rust
16//! use limbic_critic::ModulatorVector;
17//!
18//! let mods = ModulatorVector {
19//!     dopamine: 0.8,
20//!     serotonin: 0.2,
21//!     acetylcholine: 0.1,
22//!     norepinephrine: 0.0,
23//! };
24//! assert!(mods.dopamine >= 0.0);
25//! ```
26
27/// A vector of neuromodulator concentrations.
28///
29/// Critics populate these fields from an [`Environment`](crate::Environment)
30/// observation (and, for temporal critics, from internal state). Consumers
31/// typically feed the values into synaptic plasticity rules, attention
32/// gating, or other neuromodulatory pathways.
33///
34/// Field ranges depend on which critic produced the vector; see each field's
35/// documentation and the critic-level docs for exact mappings. Vectors from
36/// `try_assess` are finite and inside those ranges; `assess` may yield NaN
37/// when given non-finite observations (IEEE passthrough).
38#[derive(Debug, Clone, Copy, PartialEq, Default)]
39pub struct ModulatorVector {
40    /// Dopamine — shaped reward / objective-delta drive.
41    ///
42    /// Semantic role: a bounded scalar that downstream plasticity can use
43    /// to reinforce or weaken recent activity. [`TDCritic`](crate::TDCritic)
44    /// produces a signed value from an EMA of objective deltas, not from a
45    /// learned prediction-error network.
46    ///
47    /// Ranges by critic:
48    /// - [`SimpleCritic`](crate::SimpleCritic): clamped to **`[0.0, 1.0]`**
49    ///   (non-negative objective mapped through; negative objective → `0.0`).
50    /// - [`TDCritic`](crate::TDCritic): signed, clamped to **`[-1.0, 1.0]`**
51    ///   after an EMA of the temporal-difference error is passed through
52    ///   `tanh`.
53    pub dopamine: f32,
54
55    /// Serotonin — risk / volatility.
56    ///
57    /// Semantic role: tracks environmental uncertainty or risk load. Both
58    /// critics read this from [`Environment::volatility`](crate::Environment::volatility)
59    /// and clamp it to **`[0.0, 1.0]`**.
60    pub serotonin: f32,
61
62    /// Acetylcholine — focus / surprise.
63    ///
64    /// Semantic role: elevates attention or learning rate when the world is
65    /// novel or outcomes are unexpected.
66    ///
67    /// Ranges by critic (both clamp to **`[0.0, 1.0]`**):
68    /// - [`SimpleCritic`](crate::SimpleCritic): taken from
69    ///   [`Environment::surprise`](crate::Environment::surprise).
70    /// - [`TDCritic`](crate::TDCritic): derived as `abs(td_error).tanh()`,
71    ///   independent of `Environment::surprise`.
72    pub acetylcholine: f32,
73
74    /// Norepinephrine — stress / instability.
75    ///
76    /// Semantic role: reflects system pressure (error rates, thermal load,
77    /// latency spikes, etc.). Both critics map
78    /// [`Environment::stress`](crate::Environment::stress) into this field
79    /// and clamp it to **`[0.0, 1.0]`**.
80    pub norepinephrine: f32,
81}