use crate::error::Result;
use crate::optimizers::Optimizer;
use scirs2_core::ndarray::{Array1, Array2, ArrayBase, Data, DataMut, Dimension};
use scirs2_core::numeric::Float;
use std::collections::{HashMap, VecDeque};
use std::fmt::Debug;
use std::time::{Duration, Instant};
pub mod energy_efficient;
pub mod event_driven;
pub mod spike_based;
pub use energy_efficient::{EnergyBudget, EnergyEfficientOptimizer, EnergyOptimizationStrategy};
pub use event_driven::{EventDrivenConfig, EventDrivenOptimizer, EventType};
pub use spike_based::{SpikeTrainOptimizer, SpikingConfig, SpikingOptimizer};
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum NeuromorphicPlatform {
IntelLoihi,
SpiNNaker,
IBMTrueNorth,
BrainChipAkida,
Research,
Custom(String),
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct NeuromorphicConfig<T: Float + Debug + Send + Sync + 'static> {
pub platform: NeuromorphicPlatform,
pub spike_config: SpikingConfig<T>,
pub event_config: EventDrivenConfig<T>,
pub energy_config: EnergyOptimizationConfig<T>,
pub temporal_coding: bool,
pub rate_coding: bool,
pub stdp_config: STDPConfig<T>,
pub membrane_dynamics: MembraneDynamicsConfig<T>,
pub plasticity_model: PlasticityModel,
pub homeostatic_plasticity: bool,
pub metaplasticity: bool,
pub population_config: PopulationConfig,
}
#[derive(Debug, Clone)]
pub struct STDPConfig<T: Float + Debug + Send + Sync + 'static> {
pub learning_rate_pot: T,
pub learning_rate_dep: T,
pub tau_pot: T,
pub tau_dep: T,
pub weight_max: T,
pub weight_min: T,
pub enable_triplet: bool,
pub triplet_learning_rate: T,
}
#[derive(Debug, Clone)]
pub struct MembraneDynamicsConfig<T: Float + Debug + Send + Sync + 'static> {
pub tau_membrane: T,
pub resting_potential: T,
pub threshold_potential: T,
pub reset_potential: T,
pub refractory_period: T,
pub capacitance: T,
pub leak_conductance: T,
pub adaptive_threshold: bool,
pub threshold_adaptation_tau: T,
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub enum PlasticityModel {
Hebbian,
AntiHebbian,
STDP,
TripletSTDP,
VoltageDependentSTDP,
CalciumBased,
BCM,
Oja,
}
#[derive(Debug, Clone)]
pub struct PopulationConfig {
pub population_size: usize,
pub lateral_inhibition: bool,
pub inhibition_strength: f64,
pub winner_take_all: bool,
pub coding_strategy: PopulationCodingStrategy,
pub enable_bursting: bool,
pub synchronization: SynchronizationMechanism,
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub enum PopulationCodingStrategy {
Distributed,
Sparse,
Local,
Vector,
RankOrder,
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub enum SynchronizationMechanism {
None,
GlobalClock,
PhaseLocked,
Adaptive,
NetworkOscillations,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct EnergyOptimizationConfig<T: Float + Debug + Send + Sync + 'static> {
pub energy_budget: T,
pub strategy: EnergyOptimizationStrategy,
pub dynamic_voltage_scaling: bool,
pub clock_gating: bool,
pub power_gating: bool,
pub sleep_mode_config: SleepModeConfig<T>,
pub monitoring_frequency: Duration,
pub thermal_management: ThermalManagementConfig<T>,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct SleepModeConfig<T: Float + Debug + Send + Sync + 'static> {
pub enable_sleep_mode: bool,
pub sleep_threshold: Duration,
pub wakeup_time: T,
pub sleep_power: T,
pub wakeup_energy: T,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ThermalManagementConfig<T: Float + Debug + Send + Sync + 'static> {
pub enable_thermal_management: bool,
pub target_temperature: T,
pub max_temperature: T,
pub thermal_time_constant: T,
pub throttling_strategy: ThermalThrottlingStrategy,
}
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub enum ThermalThrottlingStrategy {
FrequencyScaling,
VoltageScaling,
ActivityReduction,
SelectiveShutdown,
DynamicLoadBalancing,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct Spike<T: Float + Debug + Send + Sync + 'static> {
pub neuron_id: usize,
pub time: T,
pub amplitude: T,
pub width: Option<T>,
pub weight: T,
pub presynaptic_id: Option<usize>,
pub postsynaptic_id: Option<usize>,
}
#[derive(Debug, Clone)]
pub struct SpikeTrain<T: Float + Debug + Send + Sync + 'static> {
pub neuron_id: usize,
pub spike_times: Vec<T>,
pub inter_spike_intervals: Vec<T>,
pub firing_rate: T,
pub duration: T,
pub spike_count: usize,
}
impl<T: Float + Debug + Send + Sync + 'static + std::iter::Sum> SpikeTrain<T> {
pub fn new(neuron_id: usize, spike_times: Vec<T>) -> Self {
let spike_count = spike_times.len();
let duration = if spike_count > 0 {
spike_times[spike_count - 1] - spike_times[0]
} else {
T::zero()
};
let firing_rate = if duration > T::zero() {
T::from(spike_count).unwrap_or_else(|| T::zero())
/ (duration / T::from(1000.0).unwrap_or_else(|| T::zero()))
} else {
T::zero()
};
let inter_spike_intervals = if spike_count > 1 {
spike_times.windows(2).map(|w| w[1] - w[0]).collect()
} else {
Vec::new()
};
Self {
neuron_id,
spike_times,
inter_spike_intervals,
firing_rate,
duration,
spike_count,
}
}
pub fn coefficient_of_variation(&self) -> T {
if self.inter_spike_intervals.len() < 2 {
return T::zero();
}
let mean = self.inter_spike_intervals.iter().cloned().sum::<T>()
/ T::from(self.inter_spike_intervals.len()).expect("unwrap failed");
let variance = self
.inter_spike_intervals
.iter()
.map(|&isi| (isi - mean) * (isi - mean))
.sum::<T>()
/ T::from(self.inter_spike_intervals.len()).expect("unwrap failed");
variance.sqrt() / mean
}
pub fn local_variation(&self) -> T {
if self.inter_spike_intervals.len() < 2 {
return T::zero();
}
let mut lv_sum = T::zero();
for window in self.inter_spike_intervals.windows(2) {
let isi1 = window[0];
let isi2 = window[1];
let diff = isi1 - isi2;
let sum = isi1 + isi2;
if sum > T::zero() {
lv_sum = lv_sum + (diff * diff) / (sum * sum);
}
}
let three = T::from(3.0).unwrap_or_else(|| T::zero());
three * lv_sum / T::from(self.inter_spike_intervals.len() - 1).expect("unwrap failed")
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct NeuromorphicEvent<T: Float + Debug + Send + Sync + 'static> {
pub event_type: EventType,
pub timestamp: T,
pub source_neuron: usize,
pub target_neuron: Option<usize>,
pub value: T,
pub energy_cost: T,
pub priority: EventPriority,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[allow(dead_code)]
pub enum EventPriority {
Low,
Normal,
High,
Critical,
RealTime,
}
#[derive(Debug, Clone)]
pub struct NeuromorphicMetrics<T: Float + Debug + Send + Sync + 'static> {
pub total_spikes: usize,
pub average_firing_rate: T,
pub energy_consumption: T,
pub power_consumption: T,
pub timing_precision: T,
pub synaptic_ops_per_sec: T,
pub plasticity_events_per_sec: T,
pub memory_bandwidth_utilization: T,
pub thermal_efficiency: T,
pub network_synchronization: T,
}
impl<T: Float + Debug + Send + Sync + 'static> Default for NeuromorphicMetrics<T> {
fn default() -> Self {
Self {
total_spikes: 0,
average_firing_rate: T::zero(),
energy_consumption: T::zero(),
power_consumption: T::zero(),
timing_precision: T::from(0.1).unwrap_or_else(|| T::zero()), synaptic_ops_per_sec: T::zero(),
plasticity_events_per_sec: T::zero(),
memory_bandwidth_utilization: T::zero(),
thermal_efficiency: T::one(),
network_synchronization: T::zero(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for NeuromorphicConfig<T> {
fn default() -> Self {
Self {
platform: NeuromorphicPlatform::IntelLoihi,
spike_config: SpikingConfig::default(),
event_config: EventDrivenConfig::default(),
energy_config: EnergyOptimizationConfig::default(),
temporal_coding: true,
rate_coding: false,
stdp_config: STDPConfig::default(),
membrane_dynamics: MembraneDynamicsConfig::default(),
plasticity_model: PlasticityModel::STDP,
homeostatic_plasticity: false,
metaplasticity: false,
population_config: PopulationConfig::default(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for STDPConfig<T> {
fn default() -> Self {
Self {
learning_rate_pot: T::from(0.01).unwrap_or_else(|| T::zero()),
learning_rate_dep: T::from(0.01).unwrap_or_else(|| T::zero()),
tau_pot: T::from(20.0).unwrap_or_else(|| T::zero()),
tau_dep: T::from(20.0).unwrap_or_else(|| T::zero()),
weight_max: T::one(),
weight_min: T::zero(),
enable_triplet: false,
triplet_learning_rate: T::from(0.001).unwrap_or_else(|| T::zero()),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for MembraneDynamicsConfig<T> {
fn default() -> Self {
Self {
tau_membrane: T::from(20.0).unwrap_or_else(|| T::zero()),
resting_potential: T::from(-70.0).unwrap_or_else(|| T::zero()),
threshold_potential: T::from(-55.0).unwrap_or_else(|| T::zero()),
reset_potential: T::from(-80.0).unwrap_or_else(|| T::zero()),
refractory_period: T::from(2.0).unwrap_or_else(|| T::zero()),
capacitance: T::from(100.0).unwrap_or_else(|| T::zero()),
leak_conductance: T::from(10.0).unwrap_or_else(|| T::zero()),
adaptive_threshold: false,
threshold_adaptation_tau: T::from(100.0).unwrap_or_else(|| T::zero()),
}
}
}
impl Default for PopulationConfig {
fn default() -> Self {
Self {
population_size: 1000,
lateral_inhibition: false,
inhibition_strength: 0.1,
winner_take_all: false,
coding_strategy: PopulationCodingStrategy::Distributed,
enable_bursting: false,
synchronization: SynchronizationMechanism::None,
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for EnergyOptimizationConfig<T> {
fn default() -> Self {
Self {
energy_budget: T::from(10.0).unwrap_or_else(|| T::zero()), strategy: EnergyOptimizationStrategy::DynamicVoltageScaling,
dynamic_voltage_scaling: true,
clock_gating: true,
power_gating: false,
sleep_mode_config: SleepModeConfig::default(),
monitoring_frequency: Duration::from_millis(100),
thermal_management: ThermalManagementConfig::default(),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for SleepModeConfig<T> {
fn default() -> Self {
Self {
enable_sleep_mode: true,
sleep_threshold: Duration::from_millis(100),
wakeup_time: T::from(1.0).unwrap_or_else(|| T::zero()),
sleep_power: T::from(0.1).unwrap_or_else(|| T::zero()),
wakeup_energy: T::from(0.01).unwrap_or_else(|| T::zero()),
}
}
}
impl<T: Float + Debug + Send + Sync + 'static> Default for ThermalManagementConfig<T> {
fn default() -> Self {
Self {
enable_thermal_management: true,
target_temperature: T::from(65.0).unwrap_or_else(|| T::zero()),
max_temperature: T::from(85.0).unwrap_or_else(|| T::zero()),
thermal_time_constant: T::from(10.0).unwrap_or_else(|| T::zero()),
throttling_strategy: ThermalThrottlingStrategy::FrequencyScaling,
}
}
}