1use scirs2_core::numeric::Float;
8use std::fmt::Debug;
9use std::time::Duration;
10
11pub mod energy_efficient;
12pub mod event_driven;
13pub mod spike_based;
14
15pub(crate) fn to_generic_or<F: Float>(value: f64, fallback: F) -> F {
21 F::from(value).unwrap_or(fallback)
22}
23
24pub use energy_efficient::{EnergyBudget, EnergyEfficientOptimizer, EnergyOptimizationStrategy};
26pub use event_driven::{EventDrivenConfig, EventDrivenOptimizer, EventType};
27pub use spike_based::{SpikeTrainOptimizer, SpikingConfig, SpikingOptimizer};
28
29#[derive(Debug, Clone)]
31pub enum NeuromorphicPlatform {
32 IntelLoihi,
34
35 SpiNNaker,
37
38 IBMTrueNorth,
40
41 BrainChipAkida,
43
44 Research,
46
47 Custom(String),
49}
50
51#[derive(Debug, Clone)]
53pub struct NeuromorphicConfig<T: Float + Debug + Send + Sync + 'static> {
54 pub platform: NeuromorphicPlatform,
56
57 pub spike_config: SpikingConfig<T>,
59
60 pub event_config: EventDrivenConfig<T>,
62
63 pub energy_config: EnergyOptimizationConfig<T>,
65
66 pub temporal_coding: bool,
68
69 pub rate_coding: bool,
71
72 pub stdp_config: STDPConfig<T>,
74
75 pub membrane_dynamics: MembraneDynamicsConfig<T>,
77
78 pub plasticity_model: PlasticityModel,
80
81 pub homeostatic_plasticity: bool,
83
84 pub metaplasticity: bool,
86
87 pub population_config: PopulationConfig,
89}
90
91#[derive(Debug, Clone)]
93pub struct STDPConfig<T: Float + Debug + Send + Sync + 'static> {
94 pub learning_rate_pot: T,
96
97 pub learning_rate_dep: T,
99
100 pub tau_pot: T,
102
103 pub tau_dep: T,
105
106 pub weight_max: T,
108
109 pub weight_min: T,
111
112 pub enable_triplet: bool,
114
115 pub triplet_learning_rate: T,
117}
118
119#[derive(Debug, Clone)]
121pub struct MembraneDynamicsConfig<T: Float + Debug + Send + Sync + 'static> {
122 pub tau_membrane: T,
124
125 pub resting_potential: T,
127
128 pub threshold_potential: T,
130
131 pub reset_potential: T,
133
134 pub refractory_period: T,
136
137 pub capacitance: T,
139
140 pub leak_conductance: T,
142
143 pub adaptive_threshold: bool,
145
146 pub threshold_adaptation_tau: T,
148}
149
150#[derive(Debug, Clone, Copy)]
152pub enum PlasticityModel {
153 Hebbian,
155
156 AntiHebbian,
158
159 STDP,
161
162 TripletSTDP,
164
165 VoltageDependentSTDP,
167
168 CalciumBased,
170
171 BCM,
173
174 Oja,
176}
177
178#[derive(Debug, Clone)]
180pub struct PopulationConfig {
181 pub population_size: usize,
183
184 pub lateral_inhibition: bool,
186
187 pub inhibition_strength: f64,
189
190 pub winner_take_all: bool,
192
193 pub coding_strategy: PopulationCodingStrategy,
195
196 pub enable_bursting: bool,
198
199 pub synchronization: SynchronizationMechanism,
201}
202
203#[derive(Debug, Clone, Copy)]
205pub enum PopulationCodingStrategy {
206 Distributed,
208
209 Sparse,
211
212 Local,
214
215 Vector,
217
218 RankOrder,
220}
221
222#[derive(Debug, Clone, Copy)]
224pub enum SynchronizationMechanism {
225 None,
227
228 GlobalClock,
230
231 PhaseLocked,
233
234 Adaptive,
236
237 NetworkOscillations,
239}
240
241#[derive(Debug, Clone)]
243pub struct EnergyOptimizationConfig<T: Float + Debug + Send + Sync + 'static> {
244 pub energy_budget: T,
246
247 pub strategy: EnergyOptimizationStrategy,
249
250 pub dynamic_voltage_scaling: bool,
252
253 pub clock_gating: bool,
255
256 pub power_gating: bool,
258
259 pub sleep_mode_config: SleepModeConfig<T>,
261
262 pub monitoring_frequency: Duration,
264
265 pub thermal_management: ThermalManagementConfig<T>,
267}
268
269#[derive(Debug, Clone)]
271pub struct SleepModeConfig<T: Float + Debug + Send + Sync + 'static> {
272 pub enable_sleep_mode: bool,
274
275 pub sleep_threshold: Duration,
277
278 pub wakeup_time: T,
280
281 pub sleep_power: T,
283
284 pub wakeup_energy: T,
286}
287
288#[derive(Debug, Clone)]
290pub struct ThermalManagementConfig<T: Float + Debug + Send + Sync + 'static> {
291 pub enable_thermal_management: bool,
293
294 pub target_temperature: T,
296
297 pub max_temperature: T,
299
300 pub thermal_time_constant: T,
302
303 pub throttling_strategy: ThermalThrottlingStrategy,
305}
306
307#[derive(Debug, Clone, Copy)]
309pub enum ThermalThrottlingStrategy {
310 FrequencyScaling,
312
313 VoltageScaling,
315
316 ActivityReduction,
318
319 SelectiveShutdown,
321
322 DynamicLoadBalancing,
324}
325
326#[derive(Debug, Clone)]
328pub struct Spike<T: Float + Debug + Send + Sync + 'static> {
329 pub neuron_id: usize,
331
332 pub time: T,
334
335 pub amplitude: T,
337
338 pub width: Option<T>,
340
341 pub weight: T,
343
344 pub presynaptic_id: Option<usize>,
346
347 pub postsynaptic_id: Option<usize>,
349}
350
351#[derive(Debug, Clone)]
353pub struct SpikeTrain<T: Float + Debug + Send + Sync + 'static> {
354 pub neuron_id: usize,
356
357 pub spike_times: Vec<T>,
359
360 pub inter_spike_intervals: Vec<T>,
362
363 pub firing_rate: T,
365
366 pub duration: T,
368
369 pub spike_count: usize,
371}
372
373impl<T: Float + Debug + Send + Sync + 'static + std::iter::Sum> SpikeTrain<T> {
374 pub fn new(neuron_id: usize, spike_times: Vec<T>) -> Self {
376 let spike_count = spike_times.len();
377 let duration = if spike_count > 0 {
378 spike_times[spike_count - 1] - spike_times[0]
379 } else {
380 T::zero()
381 };
382
383 let firing_rate = if duration > T::zero() {
384 T::from(spike_count).unwrap_or_else(|| T::zero())
385 / (duration / T::from(1000.0).unwrap_or_else(|| T::zero()))
386 } else {
387 T::zero()
388 };
389
390 let inter_spike_intervals = if spike_count > 1 {
391 spike_times.windows(2).map(|w| w[1] - w[0]).collect()
392 } else {
393 Vec::new()
394 };
395
396 Self {
397 neuron_id,
398 spike_times,
399 inter_spike_intervals,
400 firing_rate,
401 duration,
402 spike_count,
403 }
404 }
405
406 pub fn coefficient_of_variation(&self) -> T {
408 if self.inter_spike_intervals.len() < 2 {
409 return T::zero();
410 }
411
412 let count = to_generic_or(self.inter_spike_intervals.len() as f64, T::one());
413 let mean = self.inter_spike_intervals.iter().cloned().sum::<T>() / count;
414
415 let variance = self
416 .inter_spike_intervals
417 .iter()
418 .map(|&isi| (isi - mean) * (isi - mean))
419 .sum::<T>()
420 / count;
421
422 if mean == T::zero() {
423 return T::zero();
424 }
425 variance.sqrt() / mean
426 }
427
428 pub fn local_variation(&self) -> T {
430 if self.inter_spike_intervals.len() < 2 {
431 return T::zero();
432 }
433
434 let mut lv_sum = T::zero();
435 for window in self.inter_spike_intervals.windows(2) {
436 let isi1 = window[0];
437 let isi2 = window[1];
438 let diff = isi1 - isi2;
439 let sum = isi1 + isi2;
440
441 if sum > T::zero() {
442 lv_sum = lv_sum + (diff * diff) / (sum * sum);
443 }
444 }
445
446 let three = to_generic_or(3.0, T::one());
447 let denom = to_generic_or((self.inter_spike_intervals.len() - 1) as f64, T::one());
448 three * lv_sum / denom
449 }
450
451 pub fn record_spike(&mut self, time: T) {
460 if let Some(&last) = self.spike_times.last() {
461 self.inter_spike_intervals.push(time - last);
462 }
463 self.spike_times.push(time);
464 self.spike_count += 1;
465
466 self.duration = if self.spike_count > 1 {
467 self.spike_times[self.spike_count - 1] - self.spike_times[0]
468 } else {
469 T::zero()
470 };
471
472 self.firing_rate = if self.duration > T::zero() {
473 to_generic_or(self.spike_count as f64, T::zero())
474 / (self.duration / to_generic_or(1000.0, T::one()))
475 } else {
476 T::zero()
477 };
478 }
479}
480
481#[derive(Debug, Clone)]
483pub struct NeuromorphicEvent<T: Float + Debug + Send + Sync + 'static> {
484 pub event_type: EventType,
486
487 pub timestamp: T,
489
490 pub source_neuron: usize,
492
493 pub target_neuron: Option<usize>,
495
496 pub value: T,
498
499 pub energy_cost: T,
501
502 pub priority: EventPriority,
504}
505
506#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
508pub enum EventPriority {
509 Low,
510 Normal,
511 High,
512 Critical,
513 RealTime,
514}
515
516#[derive(Debug, Clone)]
518pub struct NeuromorphicMetrics<T: Float + Debug + Send + Sync + 'static> {
519 pub total_spikes: usize,
521
522 pub average_firing_rate: T,
524
525 pub energy_consumption: T,
527
528 pub power_consumption: T,
530
531 pub timing_precision: T,
533
534 pub synaptic_ops_per_sec: T,
536
537 pub plasticity_events_per_sec: T,
539
540 pub memory_bandwidth_utilization: T,
542
543 pub thermal_efficiency: T,
545
546 pub network_synchronization: T,
548}
549
550impl<T: Float + Debug + Send + Sync + 'static> Default for NeuromorphicMetrics<T> {
551 fn default() -> Self {
552 Self {
553 total_spikes: 0,
554 average_firing_rate: T::zero(),
555 energy_consumption: T::zero(),
556 power_consumption: T::zero(),
557 timing_precision: T::from(0.1).unwrap_or_else(|| T::zero()), synaptic_ops_per_sec: T::zero(),
559 plasticity_events_per_sec: T::zero(),
560 memory_bandwidth_utilization: T::zero(),
561 thermal_efficiency: T::one(),
562 network_synchronization: T::zero(),
563 }
564 }
565}
566
567impl<T: Float + Debug + Send + Sync + 'static> Default for NeuromorphicConfig<T> {
568 fn default() -> Self {
569 Self {
570 platform: NeuromorphicPlatform::IntelLoihi,
571 spike_config: SpikingConfig::default(),
572 event_config: EventDrivenConfig::default(),
573 energy_config: EnergyOptimizationConfig::default(),
574 temporal_coding: true,
575 rate_coding: false,
576 stdp_config: STDPConfig::default(),
577 membrane_dynamics: MembraneDynamicsConfig::default(),
578 plasticity_model: PlasticityModel::STDP,
579 homeostatic_plasticity: false,
580 metaplasticity: false,
581 population_config: PopulationConfig::default(),
582 }
583 }
584}
585
586impl<T: Float + Debug + Send + Sync + 'static> Default for STDPConfig<T> {
587 fn default() -> Self {
588 Self {
589 learning_rate_pot: T::from(0.01).unwrap_or_else(|| T::zero()),
590 learning_rate_dep: T::from(0.01).unwrap_or_else(|| T::zero()),
591 tau_pot: T::from(20.0).unwrap_or_else(|| T::zero()),
592 tau_dep: T::from(20.0).unwrap_or_else(|| T::zero()),
593 weight_max: T::one(),
594 weight_min: T::zero(),
595 enable_triplet: false,
596 triplet_learning_rate: T::from(0.001).unwrap_or_else(|| T::zero()),
597 }
598 }
599}
600
601impl<T: Float + Debug + Send + Sync + 'static> Default for MembraneDynamicsConfig<T> {
602 fn default() -> Self {
603 Self {
604 tau_membrane: T::from(20.0).unwrap_or_else(|| T::zero()),
605 resting_potential: T::from(-70.0).unwrap_or_else(|| T::zero()),
606 threshold_potential: T::from(-55.0).unwrap_or_else(|| T::zero()),
607 reset_potential: T::from(-80.0).unwrap_or_else(|| T::zero()),
608 refractory_period: T::from(2.0).unwrap_or_else(|| T::zero()),
609 capacitance: T::from(100.0).unwrap_or_else(|| T::zero()),
610 leak_conductance: T::from(10.0).unwrap_or_else(|| T::zero()),
611 adaptive_threshold: false,
612 threshold_adaptation_tau: T::from(100.0).unwrap_or_else(|| T::zero()),
613 }
614 }
615}
616
617impl Default for PopulationConfig {
618 fn default() -> Self {
619 Self {
620 population_size: 1000,
621 lateral_inhibition: false,
622 inhibition_strength: 0.1,
623 winner_take_all: false,
624 coding_strategy: PopulationCodingStrategy::Distributed,
625 enable_bursting: false,
626 synchronization: SynchronizationMechanism::None,
627 }
628 }
629}
630
631impl<T: Float + Debug + Send + Sync + 'static> Default for EnergyOptimizationConfig<T> {
632 fn default() -> Self {
633 Self {
634 energy_budget: T::from(10.0).unwrap_or_else(|| T::zero()), strategy: EnergyOptimizationStrategy::DynamicVoltageScaling,
636 dynamic_voltage_scaling: true,
637 clock_gating: true,
638 power_gating: false,
639 sleep_mode_config: SleepModeConfig::default(),
640 monitoring_frequency: Duration::from_millis(100),
641 thermal_management: ThermalManagementConfig::default(),
642 }
643 }
644}
645
646impl<T: Float + Debug + Send + Sync + 'static> Default for SleepModeConfig<T> {
647 fn default() -> Self {
648 Self {
649 enable_sleep_mode: true,
650 sleep_threshold: Duration::from_millis(100),
651 wakeup_time: T::from(1.0).unwrap_or_else(|| T::zero()),
652 sleep_power: T::from(0.1).unwrap_or_else(|| T::zero()),
653 wakeup_energy: T::from(0.01).unwrap_or_else(|| T::zero()),
654 }
655 }
656}
657
658impl<T: Float + Debug + Send + Sync + 'static> Default for ThermalManagementConfig<T> {
659 fn default() -> Self {
660 Self {
661 enable_thermal_management: true,
662 target_temperature: T::from(65.0).unwrap_or_else(|| T::zero()),
663 max_temperature: T::from(85.0).unwrap_or_else(|| T::zero()),
664 thermal_time_constant: T::from(10.0).unwrap_or_else(|| T::zero()),
665 throttling_strategy: ThermalThrottlingStrategy::FrequencyScaling,
666 }
667 }
668}