1use crate::config::Config;
2use crate::effector::{Effector, EffectorID};
3use crate::error::*;
4use crate::id::ID;
5use crate::neuron::{Impulse, Neuron, NeuronID, Position, Synapse};
6use crate::sensor::{Sensor, SensorID};
7use crate::Scalar;
8use rand::{thread_rng, Rng};
9#[cfg(feature = "parallel")]
10use rayon::prelude::*;
11use serde::{Deserialize, Serialize};
12use std::ops::Range;
13
14#[cfg(feature = "parallel")]
15macro_rules! iter {
16 ($v:expr) => {
17 $v.par_iter()
18 };
19}
20#[cfg(not(feature = "parallel"))]
21macro_rules! iter {
22 ($v:expr) => {
23 $v.iter()
24 };
25}
26
27#[cfg(feature = "parallel")]
28macro_rules! iter_mut {
29 ($v:expr) => {
30 $v.par_iter_mut()
31 };
32}
33#[cfg(not(feature = "parallel"))]
34macro_rules! iter_mut {
35 ($v:expr) => {
36 $v.iter_mut()
37 };
38}
39
40pub mod activity {
41 pub const NONE: usize = 0;
42 pub const CONNECTIONS: usize = 1;
43 pub const IMPULSES: usize = 1 << 1;
44 pub const SENSORS: usize = 1 << 2;
45 pub const EFFECTORS: usize = 1 << 3;
46 pub const NEURONS: usize = 1 << 4;
47 pub const ALL: usize = 0xFF;
48}
49
50pub type BrainID = ID<Brain>;
51
52#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
53#[repr(C)]
54pub struct BrainActivityMap {
55 pub connections: Vec<(Position, Position, Scalar)>,
57 pub impulses: Vec<(Position, Position, Scalar)>,
59 pub sensors: Vec<Position>,
61 pub effectors: Vec<Position>,
63 pub neurons: Vec<Position>,
65}
66
67#[derive(Debug, Clone)]
68#[repr(C)]
69pub struct BrainActivityStats {
70 pub neurons_count: usize,
71 pub synapses_count: usize,
72 pub impulses_count: usize,
73 pub neurons_potential: (Scalar, Range<Scalar>),
75 pub impulses_potential: (Scalar, Range<Scalar>),
77 pub all_potential: (Scalar, Range<Scalar>),
79 pub incoming_neuron_connections: Range<usize>,
81 pub outgoing_neuron_connections: Range<usize>,
83 pub synapses_receptors: Range<Scalar>,
85}
86
87impl Default for BrainActivityStats {
88 fn default() -> Self {
89 Self {
90 neurons_count: 0,
91 synapses_count: 0,
92 impulses_count: 0,
93 neurons_potential: (0.0, 0.0..0.0),
94 impulses_potential: (0.0, 0.0..0.0),
95 all_potential: (0.0, 0.0..0.0),
96 incoming_neuron_connections: 0..0,
97 outgoing_neuron_connections: 0..0,
98 synapses_receptors: 0.0..0.0,
99 }
100 }
101}
102
103#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
104pub struct Brain {
105 id: BrainID,
106 neurons: Vec<Neuron>,
107 synapses: Vec<Synapse>,
108 sensors: Vec<Sensor>,
109 effectors: Vec<Effector>,
110 config: Config,
111 new_connections_accum: Scalar,
112}
113
114impl Brain {
115 pub fn new() -> Self {
116 Self::default()
117 }
118
119 pub fn duplicate(&self) -> Self {
120 let id = Default::default();
121 let neuron_indices = iter!(self.neurons).map(|n| n.id()).collect::<Vec<_>>();
122 let neurons = iter!(self.neurons)
123 .map(|n| Neuron::new(id, n.position()))
124 .collect::<Vec<_>>();
125 let synapses = iter!(self.synapses)
126 .map(|s| {
127 #[cfg(feature = "parallel")]
128 let sindex = neuron_indices
129 .par_iter()
130 .position_any(|n| *n == s.source)
131 .unwrap();
132 #[cfg(not(feature = "parallel"))]
133 let sindex = neuron_indices.iter().position(|n| *n == s.source).unwrap();
134 #[cfg(feature = "parallel")]
135 let nindex = neuron_indices
136 .par_iter()
137 .position_any(|n| *n == s.target)
138 .unwrap();
139 #[cfg(not(feature = "parallel"))]
140 let nindex = neuron_indices.iter().position(|n| *n == s.target).unwrap();
141 Synapse {
142 source: neurons[sindex].id(),
143 target: neurons[nindex].id(),
144 distance: s.distance,
145 receptors: s.receptors,
146 impulses: vec![],
147 inactivity: 0.0,
148 }
149 })
150 .collect::<Vec<_>>();
151 let sensors = iter!(self.sensors)
152 .map(|s| {
153 #[cfg(feature = "parallel")]
154 let index = neuron_indices
155 .par_iter()
156 .position_any(|n| *n == s.target)
157 .unwrap();
158 #[cfg(not(feature = "parallel"))]
159 let index = neuron_indices.iter().position(|n| *n == s.target).unwrap();
160 Sensor {
161 id: s.id,
162 target: neurons[index].id(),
163 }
164 })
165 .collect::<Vec<_>>();
166 let effectors = iter!(self.effectors)
167 .map(|e| {
168 #[cfg(feature = "parallel")]
169 let index = neuron_indices
170 .par_iter()
171 .position_any(|n| *n == e.source)
172 .unwrap();
173 #[cfg(not(feature = "parallel"))]
174 let index = neuron_indices.iter().position(|n| *n == e.source).unwrap();
175 Effector {
176 id: e.id,
177 source: neurons[index].id(),
178 potential: 0.0,
179 }
180 })
181 .collect::<Vec<_>>();
182 Self {
183 id,
184 neurons,
185 synapses,
186 sensors,
187 effectors,
188 config: self.config.clone(),
189 new_connections_accum: 0.0,
190 }
191 }
192
193 pub fn merge(&self, other: &Self) -> Self {
194 let mut rng = thread_rng();
195 let id = Default::default();
196 let brain_a = self.duplicate();
197 let brain_b = other.duplicate();
198 let neurons_count = (brain_a.neurons.len() + brain_b.neurons.len()) / 2;
199 let synapses_count = (brain_a.synapses.len() + brain_b.synapses.len()) / 2;
200 let sensors_count = (brain_a.sensors.len() + brain_b.sensors.len()) / 2;
201 let effectors_count = (brain_a.effectors.len() + brain_b.effectors.len()) / 2;
202 let neurons = brain_a
203 .neurons
204 .iter()
205 .chain(brain_b.neurons.iter())
206 .map(|n| Neuron::with_id(n.id(), id, n.position()))
207 .collect();
208 let synapses = brain_a
209 .synapses
210 .iter()
211 .chain(brain_b.synapses.iter())
212 .cloned()
213 .collect();
214 let sensors = brain_a
215 .sensors
216 .iter()
217 .chain(brain_b.sensors.iter())
218 .cloned()
219 .collect();
220 let effectors = brain_a
221 .effectors
222 .iter()
223 .chain(brain_b.effectors.iter())
224 .cloned()
225 .collect();
226 let mut brain = Self {
227 id,
228 neurons,
229 synapses,
230 sensors,
231 effectors,
232 config: brain_a.config().merge(brain_b.config()),
233 new_connections_accum: 0.0,
234 };
235 while brain.neurons.len() > neurons_count {
236 if brain
237 .kill_neuron(
238 brain.neurons[rng.gen_range(0, brain.neurons.len()) % brain.neurons.len()].id(),
239 )
240 .is_err()
241 {
242 break;
243 }
244 }
245 while brain.sensors.len() > sensors_count {
246 let id = brain.sensors[rng.gen_range(0, brain.sensors.len()) % brain.sensors.len()].id;
247 if brain.kill_sensor(id).is_err() {
248 break;
249 }
250 }
251 while brain.effectors.len() > effectors_count {
252 let id =
253 brain.effectors[rng.gen_range(0, brain.effectors.len()) % brain.effectors.len()].id;
254 if brain.kill_effector(id).is_err() {
255 break;
256 }
257 }
258 while brain.synapses.len() > synapses_count {
259 let (from, to) = {
260 let index = rng.gen_range(0, brain.synapses.len()) % brain.synapses.len();
261 let synapse = &brain.synapses[index];
262 (synapse.source, synapse.target)
263 };
264 if brain.unbind_neurons(from, to).is_err() {
265 break;
266 }
267 }
268 brain
269 }
270
271 #[inline]
272 pub fn id(&self) -> BrainID {
273 self.id
274 }
275
276 #[inline]
277 pub fn get_neurons(&self) -> Vec<NeuronID> {
278 iter!(self.neurons).map(|n| n.id()).collect()
279 }
280
281 #[inline]
282 pub fn get_sensors(&self) -> Vec<SensorID> {
283 iter!(self.sensors).map(|s| s.id).collect()
284 }
285
286 #[inline]
287 pub fn get_effectors(&self) -> Vec<EffectorID> {
288 iter!(self.effectors).map(|e| e.id).collect()
289 }
290
291 #[inline]
292 pub fn synapses_count(&self) -> usize {
293 self.synapses.len()
294 }
295
296 #[inline]
297 pub fn get_impulses_count(&self) -> usize {
298 iter!(self.synapses).map(|s| s.impulses.len()).sum()
299 }
300
301 #[inline]
302 pub fn get_impulses_potential(&self) -> Scalar {
303 iter!(self.synapses)
304 .map(|s| iter!(s.impulses).map(|i| i.potential).sum::<Scalar>())
305 .sum::<Scalar>()
306 }
307
308 #[inline]
309 pub fn get_neurons_potential(&self) -> Scalar {
310 iter!(self.neurons).map(|n| n.potential()).sum()
311 }
312
313 #[inline]
314 pub fn get_potential(&self) -> Scalar {
315 self.get_neurons_potential() + self.get_impulses_potential()
316 }
317
318 pub fn clear(&mut self) {
319 self.neurons.clear();
320 self.synapses.clear();
321 self.sensors.clear();
322 self.effectors.clear();
323 }
324
325 #[inline]
326 pub fn config(&self) -> &Config {
327 &self.config
328 }
329
330 #[inline]
331 pub fn config_mut(&mut self) -> &mut Config {
332 &mut self.config
333 }
334
335 #[inline]
336 pub fn set_config(&mut self, config: Config) {
337 self.config = config;
338 }
339
340 #[inline]
341 pub fn neuron(&self, id: NeuronID) -> Option<&Neuron> {
342 #[cfg(feature = "parallel")]
343 {
344 self.neurons.par_iter().find_any(|n| n.id() == id)
345 }
346 #[cfg(not(feature = "parallel"))]
347 {
348 self.neurons.iter().find(|n| n.id() == id)
349 }
350 }
351
352 #[inline]
353 pub fn neuron_mut(&mut self, id: NeuronID) -> Option<&mut Neuron> {
354 #[cfg(feature = "parallel")]
355 {
356 self.neurons.par_iter_mut().find_any(|n| n.id() == id)
357 }
358 #[cfg(not(feature = "parallel"))]
359 {
360 self.neurons.iter_mut().find(|n| n.id() == id)
361 }
362 }
363
364 #[inline]
365 pub fn neurons(&self) -> &[Neuron] {
366 &self.neurons
367 }
368
369 #[inline]
370 pub fn are_neurons_connected(&self, from: NeuronID, to: NeuronID) -> bool {
371 iter!(self.synapses).any(|s| s.source == from && s.target == to)
372 }
373
374 #[inline]
375 pub fn does_neuron_has_connections(&self, id: NeuronID) -> bool {
376 iter!(self.synapses).any(|s| s.source == id || s.target == id)
377 }
378
379 #[inline]
380 pub fn get_neuron_connections_count(&self, id: NeuronID) -> (usize, usize) {
381 let incoming = iter!(self.synapses).filter(|s| s.target == id).count();
382 let outgoing = iter!(self.synapses).filter(|s| s.source == id).count();
383 (incoming, outgoing)
384 }
385
386 #[inline]
387 pub fn get_neuron_connections(&self, id: NeuronID) -> (Vec<NeuronID>, Vec<NeuronID>) {
388 let incoming = iter!(self.synapses)
389 .filter_map(|s| if s.target == id { Some(s.source) } else { None })
390 .collect();
391 let outgoing = iter!(self.synapses)
392 .filter_map(|s| if s.source == id { Some(s.target) } else { None })
393 .collect();
394 (incoming, outgoing)
395 }
396
397 pub fn create_sensor(&mut self, target: NeuronID) -> Result<SensorID> {
398 #[cfg(feature = "parallel")]
399 let sensor = self.sensors.par_iter().find_any(|s| s.target == target);
400 #[cfg(not(feature = "parallel"))]
401 let sensor = self.sensors.iter().find(|s| s.target == target);
402 if let Some(sensor) = sensor {
403 return Err(Error::NeuronIsAlreadyConnectedToSensor(target, sensor.id));
404 }
405 #[cfg(feature = "parallel")]
406 let effector = self.effectors.par_iter().find_any(|e| e.source == target);
407 #[cfg(not(feature = "parallel"))]
408 let effector = self.effectors.iter().find(|e| e.source == target);
409 if let Some(effector) = effector {
410 return Err(Error::NeuronIsAlreadyConnectedToEffector(
411 target,
412 effector.id,
413 ));
414 }
415 let sensor = Sensor {
416 id: Default::default(),
417 target,
418 };
419 let id = sensor.id;
420 self.sensors.push(sensor);
421 Ok(id)
422 }
423
424 pub fn kill_sensor(&mut self, id: SensorID) -> Result<()> {
425 #[cfg(feature = "parallel")]
426 let index = self.sensors.par_iter().position_any(|s| s.id == id);
427 #[cfg(not(feature = "parallel"))]
428 let index = self.sensors.iter().position(|s| s.id == id);
429 if let Some(index) = index {
430 self.sensors.swap_remove(index);
431 Ok(())
432 } else {
433 Err(Error::SensorDoesNotExists(id))
434 }
435 }
436
437 pub fn sensor_trigger_impulse(&mut self, id: SensorID, potential: Scalar) -> Result<()> {
438 #[cfg(feature = "parallel")]
439 let sensor = self.sensors.par_iter().find_any(|s| s.id == id);
440 #[cfg(not(feature = "parallel"))]
441 let sensor = self.sensors.iter().find(|s| s.id == id);
442 if let Some(sensor) = sensor {
443 #[cfg(feature = "parallel")]
444 let neuron = self
445 .neurons
446 .par_iter_mut()
447 .find_any(|n| n.id() == sensor.target);
448 #[cfg(not(feature = "parallel"))]
449 let neuron = self.neurons.iter_mut().find(|n| n.id() == sensor.target);
450 if let Some(neuron) = neuron {
451 neuron.push_potential(potential);
452 Ok(())
453 } else {
454 Err(Error::NeuronDoesNotExists(sensor.target))
455 }
456 } else {
457 Err(Error::SensorDoesNotExists(id))
458 }
459 }
460
461 pub fn create_effector(&mut self, source: NeuronID) -> Result<EffectorID> {
462 #[cfg(feature = "parallel")]
463 let sensor = self.sensors.par_iter().find_any(|s| s.target == source);
464 #[cfg(not(feature = "parallel"))]
465 let sensor = self.sensors.iter().find(|s| s.target == source);
466 if let Some(sensor) = sensor {
467 return Err(Error::NeuronIsAlreadyConnectedToSensor(source, sensor.id));
468 }
469 #[cfg(feature = "parallel")]
470 let effector = self.effectors.par_iter().find_any(|e| e.source == source);
471 #[cfg(not(feature = "parallel"))]
472 let effector = self.effectors.iter().find(|e| e.source == source);
473 if let Some(effector) = effector {
474 return Err(Error::NeuronIsAlreadyConnectedToEffector(
475 source,
476 effector.id,
477 ));
478 }
479 let effector = Effector {
480 id: Default::default(),
481 source,
482 potential: 0.0,
483 };
484 let id = effector.id;
485 self.effectors.push(effector);
486 Ok(id)
487 }
488
489 pub fn kill_effector(&mut self, id: EffectorID) -> Result<()> {
490 #[cfg(feature = "parallel")]
491 let index = self.effectors.par_iter().position_any(|e| e.id == id);
492 #[cfg(not(feature = "parallel"))]
493 let index = self.effectors.iter().position(|e| e.id == id);
494 if let Some(index) = index {
495 self.effectors.swap_remove(index);
496 Ok(())
497 } else {
498 Err(Error::EffectorDoesNotExists(id))
499 }
500 }
501
502 pub fn effector_potential_release(&mut self, id: EffectorID) -> Result<Scalar> {
503 #[cfg(feature = "parallel")]
504 let effector = self.effectors.par_iter_mut().find_any(|e| e.id == id);
505 #[cfg(not(feature = "parallel"))]
506 let effector = self.effectors.iter_mut().find(|e| e.id == id);
507 if let Some(effector) = effector {
508 let potential = effector.potential;
509 effector.potential = 0.0;
510 Ok(potential)
511 } else {
512 Err(Error::EffectorDoesNotExists(id))
513 }
514 }
515
516 pub fn create_neuron(&mut self, position: Position) -> NeuronID {
517 let neuron = Neuron::new(self.id, position);
518 let id = neuron.id();
519 self.neurons.push(neuron);
520 id
521 }
522
523 pub fn kill_neuron(&mut self, id: NeuronID) -> Result<()> {
524 #[cfg(feature = "parallel")]
525 let index = self.neurons.par_iter().position_any(|n| n.id() == id);
526 #[cfg(not(feature = "parallel"))]
527 let index = self.neurons.iter().position(|n| n.id() == id);
528 if let Some(index) = index {
529 self.neurons.swap_remove(index);
530 while let Some(index) = self
531 .synapses
532 .iter()
533 .position(|s| s.source == id || s.target == id)
534 {
535 self.synapses.swap_remove(index);
536 }
537 #[cfg(feature = "parallel")]
538 let index = self.sensors.par_iter().position_any(|s| s.target == id);
539 #[cfg(not(feature = "parallel"))]
540 let index = self.sensors.iter().position(|s| s.target == id);
541 while let Some(index) = index {
542 self.sensors.swap_remove(index);
543 }
544 #[cfg(feature = "parallel")]
545 let index = self.effectors.par_iter().position_any(|e| e.source == id);
546 #[cfg(not(feature = "parallel"))]
547 let index = self.effectors.iter().position(|e| e.source == id);
548 while let Some(index) = index {
549 self.effectors.swap_remove(index);
550 }
551 Ok(())
552 } else {
553 Err(Error::NeuronDoesNotExists(id))
554 }
555 }
556
557 pub fn bind_neurons(&mut self, from: NeuronID, to: NeuronID) -> Result<Option<Scalar>> {
558 if from == to {
559 return Err(Error::BindingNeuronToItSelf(from));
560 }
561 if let Some(source) = self.neuron(from) {
562 if let Some(target) = self.neuron(to) {
563 if self.are_neurons_connected(from, to) {
564 return Ok(None);
565 }
566 #[cfg(feature = "parallel")]
567 let sensor = self.sensors.par_iter().find_any(|s| s.target == to);
568 #[cfg(not(feature = "parallel"))]
569 let sensor = self.sensors.iter().find(|s| s.target == to);
570 if let Some(sensor) = sensor {
571 return Err(Error::BindingNeuronToSensor(to, sensor.id));
572 }
573 #[cfg(feature = "parallel")]
574 let effector = self.effectors.par_iter().find_any(|e| e.source == from);
575 #[cfg(not(feature = "parallel"))]
576 let effector = self.effectors.iter().find(|e| e.source == from);
577 if let Some(effector) = effector {
578 return Err(Error::BindingEffectorToNeuron(effector.id, from));
579 }
580 let distance = source.position().distance(target.position());
581 let receptors = thread_rng().gen_range(
582 self.config.default_receptors.start,
583 self.config.default_receptors.end,
584 );
585 self.synapses.push(Synapse {
586 source: from,
587 target: to,
588 distance,
589 receptors,
590 impulses: vec![],
591 inactivity: 0.0,
592 });
593 Ok(Some(receptors))
594 } else {
595 Err(Error::NeuronDoesNotExists(to))
596 }
597 } else {
598 Err(Error::NeuronDoesNotExists(from))
599 }
600 }
601
602 pub fn unbind_neurons(&mut self, from: NeuronID, to: NeuronID) -> Result<bool> {
603 if from == to {
604 return Err(Error::UnbindingNeuronFromItSelf(from));
605 }
606 if iter!(self.neurons).any(|n| n.id() == from) {
607 if iter!(self.neurons).any(|n| n.id() == to) {
608 #[cfg(feature = "parallel")]
609 let index = self
610 .synapses
611 .par_iter()
612 .position_any(|s| s.source == from && s.target == to);
613 #[cfg(not(feature = "parallel"))]
614 let index = self
615 .synapses
616 .iter()
617 .position(|s| s.source == from && s.target == to);
618 if let Some(index) = index {
619 self.synapses.swap_remove(index);
620 Ok(true)
621 } else {
622 Ok(false)
623 }
624 } else {
625 Err(Error::NeuronDoesNotExists(to))
626 }
627 } else {
628 Err(Error::NeuronDoesNotExists(from))
629 }
630 }
631
632 pub fn kill_impulses(&mut self) {
633 for neuron in &mut self.neurons {
634 neuron.fire();
635 }
636 for synapse in &mut self.synapses {
637 synapse.impulses.len();
638 }
639 for effector in &mut self.effectors {
640 effector.potential = 0.0;
641 }
642 }
643
644 pub fn process(&mut self, delta_time: Scalar) -> Result<()> {
645 if self.neurons.is_empty() {
646 return Ok(());
647 }
648
649 let Config {
650 propagation_speed,
651 action_potential_treshold,
652 synapse_inactivity_time,
653 neuron_potential_decay,
654 synapse_overdose_receptors,
655 receptors_excitation,
656 receptors_inhibition,
657 synapse_propagation_decay,
658 synapse_new_connection_receptors,
659 ..
660 } = self.config;
661
662 {
664 let dtpd = delta_time * neuron_potential_decay;
665 let neurons_triggering = iter_mut!(self.neurons)
666 .filter_map(|neuron| {
667 let potential = neuron.potential();
668 let status = if potential >= action_potential_treshold {
669 neuron.fire();
670 true
671 } else {
672 false
673 };
674 neuron.process_potential(dtpd);
675 if status {
676 Some((neuron.id(), potential))
677 } else {
678 None
679 }
680 })
681 .collect::<Vec<_>>();
682 for (id, p) in neurons_triggering {
683 let count = iter!(self.synapses)
684 .filter(|s| s.inactivity <= 0.0 && s.source == id)
685 .count();
686 if count > 0 {
687 let p = p / count as Scalar;
688 iter_mut!(self.synapses)
689 .filter(|s| s.inactivity <= 0.0 && s.source == id)
690 .for_each(|s| {
691 let under = if let Some(o) = synapse_overdose_receptors {
692 s.receptors < o
693 } else {
694 true
695 };
696 if under {
697 s.impulses.push(Impulse {
698 potential: p,
699 timeout: s.distance,
700 });
701 }
702 s.inactivity = synapse_inactivity_time;
703 });
704 }
705 }
706 }
707
708 {
710 let s = propagation_speed * delta_time;
711 let r = receptors_excitation * delta_time;
712 let d = synapse_propagation_decay * s;
713 let neurons_to_trigger = iter_mut!(self.synapses)
714 .flat_map(|synapse| {
715 let mut estimated_count = 0;
716 for impulse in &mut synapse.impulses {
717 impulse.potential -= d;
718 impulse.timeout -= s;
719 if impulse.timeout <= 0.0 {
720 estimated_count += 1;
721 }
722 }
723 synapse.receptors += estimated_count as Scalar * r;
724 let mut neurons_to_trigger = Vec::with_capacity(estimated_count);
725 if estimated_count > 0 {
726 synapse.impulses = synapse
727 .impulses
728 .iter()
729 .filter_map(|impulse| {
730 if impulse.potential <= 0.0 {
731 None
732 } else if impulse.timeout > 0.0 {
733 Some(*impulse)
734 } else {
735 neurons_to_trigger.push((synapse.target, impulse.potential));
736 None
737 }
738 })
739 .collect();
740 }
741 synapse.inactivity = (synapse.inactivity - delta_time).max(0.0);
742 neurons_to_trigger
743 })
744 .collect::<Vec<_>>();
745 iter_mut!(self.neurons).for_each(|neuron| {
746 let nid = neuron.id();
747 for (id, potential) in &neurons_to_trigger {
748 if nid == *id {
749 neuron.push_potential(*potential);
750 }
751 }
752 });
753 }
754
755 if receptors_inhibition > 0.0 {
757 let r = receptors_inhibition * delta_time;
758 let synapses_to_remove = iter_mut!(self.synapses)
759 .enumerate()
760 .filter_map(|(i, synapse)| {
761 synapse.receptors -= r;
762 if synapse.receptors <= 0.0 {
763 Some(i)
764 } else {
765 None
766 }
767 })
768 .collect::<Vec<_>>();
769 let neurons_to_reconnect = iter!(synapses_to_remove)
770 .filter_map(|index| {
771 let s = &self.synapses[*index];
772 if s.receptors <= 0.0 {
773 #[cfg(feature = "parallel")]
774 let neuron = self.neurons.par_iter().find_any(|n| n.id() == s.source);
775 #[cfg(not(feature = "parallel"))]
776 let neuron = self.neurons.iter().find(|n| n.id() == s.source);
777 if let Some(neuron) = neuron {
778 let mut rng = thread_rng();
779 if let Some(id) = self.select_neuron(neuron.position(), &mut rng) {
780 if s.source != id
781 && !self.are_neurons_connected(s.source, id)
782 && !self.are_neurons_connected(id, s.source)
783 {
784 return Some((s.source, id));
785 }
786 }
787 }
788 }
789 None
790 })
791 .collect::<Vec<_>>();
792 for index in synapses_to_remove.into_iter().rev() {
793 self.synapses.swap_remove(index);
794 }
795 for (from, to) in neurons_to_reconnect {
796 self.bind_neurons(from, to)?;
797 }
798 }
799
800 {
802 let neurons_to_remove = iter!(self.neurons)
803 .enumerate()
804 .filter_map(|(i, n)| {
805 let id = n.id();
806 if !iter!(self.synapses).any(|s| s.source == id || s.target == id) {
807 Some(i)
808 } else {
809 None
810 }
811 })
812 .collect::<Vec<_>>();
813 for index in neurons_to_remove.into_iter().rev() {
814 let id = self.neurons.swap_remove(index).id();
815 #[cfg(feature = "parallel")]
816 let index = self
817 .synapses
818 .par_iter()
819 .position_any(|s| s.source == id || s.target == id);
820 #[cfg(not(feature = "parallel"))]
821 let index = self
822 .synapses
823 .iter()
824 .position(|s| s.source == id || s.target == id);
825 while let Some(index) = index {
826 self.synapses.swap_remove(index);
827 }
828 #[cfg(feature = "parallel")]
829 let index = self.sensors.par_iter().position_any(|s| s.target == id);
830 #[cfg(not(feature = "parallel"))]
831 let index = self.sensors.iter().position(|s| s.target == id);
832 while let Some(index) = index {
833 self.sensors.swap_remove(index);
834 }
835 #[cfg(feature = "parallel")]
836 let index = self.effectors.par_iter().position_any(|e| e.source == id);
837 #[cfg(not(feature = "parallel"))]
838 let index = self.effectors.iter().position(|e| e.source == id);
839 while let Some(index) = index {
840 self.effectors.swap_remove(index);
841 }
842 }
843 }
844
845 {
847 for effector in &mut self.effectors {
848 #[cfg(feature = "parallel")]
849 let neuron = self
850 .neurons
851 .par_iter()
852 .find_any(|n| n.id() == effector.source);
853 #[cfg(not(feature = "parallel"))]
854 let neuron = self.neurons.iter().find(|n| n.id() == effector.source);
855 if let Some(neuron) = neuron {
856 effector.potential = neuron.potential();
857 }
858 }
859 }
860
861 if let Some(r) = synapse_new_connection_receptors {
863 let synapses_to_connect = iter!(self.synapses)
864 .enumerate()
865 .filter_map(|(i, s)| {
866 if s.receptors > r {
867 if let Some(neuron) = self.neuron(s.source) {
868 let mut rng = thread_rng();
869 if let Some(id) = self.select_neuron(neuron.position(), &mut rng) {
870 if s.source != id
871 && !self.are_neurons_connected(s.source, id)
872 && !self.are_neurons_connected(id, s.source)
873 {
874 return Some((i, s.source, id));
875 }
876 }
877 }
878 }
879 None
880 })
881 .collect::<Vec<_>>();
882 for (index, from, to) in synapses_to_connect.into_iter().rev() {
883 if let Some(receptors) = self.bind_neurons(from, to)? {
884 self.synapses[index].receptors -= receptors;
885 }
886 }
887 }
888
889 Ok(())
890 }
891
892 fn select_neuron<R>(&self, position: Position, rng: &mut R) -> Option<NeuronID>
893 where
894 R: Rng,
895 {
896 let srr = self.config.synapse_reconnection_range;
897 let filtered = iter!(self.neurons)
898 .filter_map(|neuron| {
899 if iter!(self.sensors).any(|s| s.target == neuron.id()) {
900 return None;
901 }
902 if let Some(srr) = srr {
903 if neuron.position().distance(position) < srr {
904 return None;
905 }
906 }
907 Some(neuron.id())
908 })
909 .collect::<Vec<_>>();
910 if filtered.is_empty() {
911 None
912 } else {
913 Some(filtered[rng.gen_range(0, filtered.len()) % filtered.len()])
914 }
915 }
916
917 #[inline]
918 pub fn build_activity_map_default(&self) -> BrainActivityMap {
919 self.build_activity_map(activity::ALL)
920 }
921
922 pub fn build_activity_map(&self, flags: usize) -> BrainActivityMap {
923 let connections = if flags & activity::CONNECTIONS != 0 {
924 iter!(self.synapses)
925 .map(|s| {
926 let from = self.neuron(s.source).unwrap().position();
927 let to = self.neuron(s.target).unwrap().position();
928 (from, to, s.receptors)
929 })
930 .collect()
931 } else {
932 vec![]
933 };
934 let impulses = if flags & activity::IMPULSES != 0 {
935 iter!(self.synapses)
936 .map(|s| {
937 let from = self.neuron(s.source).unwrap().position();
938 let to = self.neuron(s.target).unwrap().position();
939 let distance = from.distance(to);
940 iter!(s.impulses)
941 .map(|i| {
942 let factor = if distance > 0.0 {
943 1.0 - i.timeout.max(0.0).min(distance) / distance
944 } else {
945 0.0
946 };
947 (from, to, factor)
948 })
949 .collect::<Vec<_>>()
950 })
951 .flatten()
952 .collect()
953 } else {
954 vec![]
955 };
956 let sensors = if flags & activity::SENSORS != 0 {
957 iter!(self.sensors)
958 .map(|s| self.neuron(s.target).unwrap().position())
959 .collect()
960 } else {
961 vec![]
962 };
963 let effectors = if flags & activity::EFFECTORS != 0 {
964 iter!(self.effectors)
965 .map(|e| self.neuron(e.source).unwrap().position())
966 .collect()
967 } else {
968 vec![]
969 };
970 let neurons = if flags & activity::NEURONS != 0 {
971 iter!(self.neurons).map(|n| n.position()).collect()
972 } else {
973 vec![]
974 };
975
976 BrainActivityMap {
977 connections,
978 impulses,
979 sensors,
980 effectors,
981 neurons,
982 }
983 }
984
985 pub fn build_activity_stats(&self) -> BrainActivityStats {
986 let neurons_potential = self.get_neurons_potential();
987 let neurons_potential_min = iter!(self.neurons)
988 .map(|n| n.potential())
989 .min_by(|a, b| a.partial_cmp(&b).unwrap())
990 .unwrap_or(0.0);
991 let neurons_potential_max = iter!(self.neurons)
992 .map(|n| n.potential())
993 .max_by(|a, b| a.partial_cmp(&b).unwrap())
994 .unwrap_or(0.0);
995 let impulses_potential = self.get_impulses_potential();
996 let impulses_potential_min = iter!(self.synapses)
997 .map(|s| {
998 iter!(s.impulses)
999 .map(|i| i.potential)
1000 .min_by(|a, b| a.partial_cmp(&b).unwrap())
1001 .unwrap_or(0.0)
1002 })
1003 .min_by(|a, b| a.partial_cmp(&b).unwrap())
1004 .unwrap_or(0.0);
1005 let impulses_potential_max = iter!(self.synapses)
1006 .map(|s| {
1007 iter!(s.impulses)
1008 .map(|i| i.potential)
1009 .max_by(|a, b| a.partial_cmp(&b).unwrap())
1010 .unwrap_or(0.0)
1011 })
1012 .max_by(|a, b| a.partial_cmp(&b).unwrap())
1013 .unwrap_or(0.0);
1014 let neuron_connections = iter!(self.neurons)
1015 .map(|n| self.get_neuron_connections_count(n.id()))
1016 .collect::<Vec<_>>();
1017 #[cfg(feature = "parallel")]
1018 let neuron_connections_min = neuron_connections
1019 .par_iter()
1020 .cloned()
1021 .reduce(|| (0, 0), |a, b| (a.0.min(b.0), a.1.min(b.1)));
1022 #[cfg(not(feature = "parallel"))]
1023 let neuron_connections_min = neuron_connections
1024 .iter()
1025 .cloned()
1026 .fold((0, 0), |a, b| (a.0.min(b.0), a.1.min(b.1)));
1027 #[cfg(feature = "parallel")]
1028 let neuron_connections_max = neuron_connections
1029 .par_iter()
1030 .cloned()
1031 .reduce(|| (0, 0), |a, b| (a.0.max(b.0), a.1.max(b.1)));
1032 #[cfg(not(feature = "parallel"))]
1033 let neuron_connections_max = neuron_connections
1034 .iter()
1035 .cloned()
1036 .fold((0, 0), |a, b| (a.0.max(b.0), a.1.max(b.1)));
1037 let synapses_receptors_min = iter!(self.synapses)
1038 .map(|s| s.receptors)
1039 .min_by(|a, b| a.partial_cmp(&b).unwrap())
1040 .unwrap_or(0.0);
1041 let synapses_receptors_max = iter!(self.synapses)
1042 .map(|s| s.receptors)
1043 .max_by(|a, b| a.partial_cmp(&b).unwrap())
1044 .unwrap_or(0.0);
1045
1046 BrainActivityStats {
1047 neurons_count: self.neurons.len(),
1048 synapses_count: self.synapses.len(),
1049 impulses_count: self.get_impulses_count(),
1050 neurons_potential: (
1051 neurons_potential,
1052 neurons_potential_min..neurons_potential_max,
1053 ),
1054 impulses_potential: (
1055 impulses_potential,
1056 impulses_potential_min..impulses_potential_max,
1057 ),
1058 all_potential: (
1059 neurons_potential + impulses_potential,
1060 neurons_potential_min.min(impulses_potential_min)
1061 ..neurons_potential_max.max(impulses_potential_max),
1062 ),
1063 incoming_neuron_connections: neuron_connections_min.0..neuron_connections_max.0,
1064 outgoing_neuron_connections: neuron_connections_min.1..neuron_connections_max.1,
1065 synapses_receptors: synapses_receptors_min..synapses_receptors_max,
1066 }
1067 }
1068
1069 pub fn ignite_random_synapses(&mut self, count: usize, potential: Range<Scalar>) {
1070 let mut rng = thread_rng();
1071 for _ in 0..count {
1072 let index = rng.gen_range(0, self.synapses.len()) % self.synapses.len();
1073 let synapse = &mut self.synapses[index];
1074 synapse.impulses.push(Impulse {
1075 potential: if potential.end <= potential.start {
1076 potential.end
1077 } else {
1078 rng.gen_range(potential.start, potential.end)
1079 },
1080 timeout: rng.gen_range(0.0, synapse.distance),
1081 });
1082 }
1083 }
1084}