Skip to main content

swarmkit/
particle_init.rs

1//! Traits for producing initial particle swarms.
2//!
3//! [`ParticleInit`] is the standalone case. [`ParticleInitDependent`] is
4//! for inner searches inside [`crate::NestedMover`], where the init seeds
5//! around the outer particle's current position.
6
7use crate::{Group, Particle, Unit};
8use rand::Rng;
9
10/// Initializes an inner swarm seeded around the outer particle's position.
11pub trait ParticleInitDependent {
12    /// Outer-search unit.
13    type TIn: Unit;
14    /// Inner-search unit being produced.
15    type TOut: Unit;
16
17    /// One initial position per particle.
18    fn init_pos<R: Rng>(&self, rng: &mut R, p: Self::TIn) -> Vec<Self::TOut>;
19    /// One initial velocity per particle.
20    fn init_vel<R: Rng>(&self, rng: &mut R, p: Self::TIn) -> Vec<Self::TOut>;
21
22    /// Zip `init_pos` and `init_vel` into a [`Group`] with `f64::MIN`
23    /// fitness; the inner searcher's first fitness pass overwrites it.
24    fn init_dep<R: Rng>(&self, rng: &mut R, p: Self::TIn) -> Group<Self::TOut> {
25        let positions = self.init_pos(rng, p);
26        let velocities = self.init_vel(rng, p);
27        debug_assert_eq!(
28            positions.len(),
29            velocities.len(),
30            "init_pos and init_vel must produce equal-length vectors",
31        );
32        let mut group = Group::<Self::TOut>::with_capacity(positions.len());
33        for (pos, vel) in positions.into_iter().zip(velocities) {
34            group.push(Particle {
35                pos,
36                vel,
37                fit: f64::MIN,
38                best_pos: pos,
39                best_fit: f64::MIN,
40            });
41        }
42        group
43    }
44}
45
46/// Initializes a standalone swarm.
47pub trait ParticleInit {
48    /// The particle unit.
49    type T: Unit;
50
51    /// One initial position per particle.
52    fn init_pos<R: Rng>(&self, rng: &mut R) -> Vec<Self::T>;
53    /// One initial velocity per particle.
54    fn init_vel<R: Rng>(&self, rng: &mut R) -> Vec<Self::T>;
55
56    /// Zip `init_pos` and `init_vel` into a [`Group`] with `f64::MIN`
57    /// fitness; the searcher's first fitness pass overwrites it.
58    fn init<R: Rng>(&self, rng: &mut R) -> Group<Self::T> {
59        let positions = self.init_pos(rng);
60        let velocities = self.init_vel(rng);
61        debug_assert_eq!(
62            positions.len(),
63            velocities.len(),
64            "init_pos and init_vel must produce equal-length vectors",
65        );
66        let mut group = Group::<Self::T>::with_capacity(positions.len());
67        for (pos, vel) in positions.into_iter().zip(velocities) {
68            group.push(Particle {
69                pos,
70                vel,
71                fit: f64::MIN,
72                best_pos: pos,
73                best_fit: f64::MIN,
74            });
75        }
76        group
77    }
78}