use crate::error::ScirsResult;
use scirs2_core::ndarray::{Array1, Array2};
use scirs2_core::random::{Rng, RngExt};
use std::collections::HashMap;
use std::sync::Arc;
use super::{
cuda_kernels::ParticleSwarmKernel,
memory_management::GpuMemoryPool,
tensor_core_optimization::{TensorCoreOptimizationConfig, TensorCoreOptimizer},
GpuFunction, GpuOptimizationConfig, GpuOptimizationContext,
};
use crate::result::OptimizeResults;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SwarmAlgorithm {
AdvancedParticleSwarm,
AntColonyOptimization,
ArtificialBeeColony,
FireflyOptimization,
CuckooSearch,
HybridMultiSwarm,
BacterialForaging,
GreyWolfOptimization,
WhaleOptimization,
AdaptiveEnsemble,
}
#[derive(Clone)]
pub struct AdvancedSwarmConfig {
pub algorithm: SwarmAlgorithm,
pub swarm_size: usize,
pub num_swarms: usize,
pub gpuconfig: GpuOptimizationConfig,
pub max_nit: usize,
pub diversity_threshold: f64,
pub elite_rate: f64,
pub migration_frequency: usize,
pub adaptive_topology: bool,
pub use_tensor_cores: bool,
pub mixed_precision: bool,
pub simd_level: SimdLevel,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SimdLevel {
None,
Basic,
Advanced,
Maximum,
}
impl Default for AdvancedSwarmConfig {
fn default() -> Self {
Self {
algorithm: SwarmAlgorithm::AdaptiveEnsemble,
swarm_size: 10000, num_swarms: 8, gpuconfig: GpuOptimizationConfig::default(),
max_nit: 1000,
diversity_threshold: 1e-6,
elite_rate: 0.1,
migration_frequency: 50,
adaptive_topology: true,
use_tensor_cores: true,
mixed_precision: true,
simd_level: SimdLevel::Advanced,
}
}
}
pub struct AdvancedParallelSwarmOptimizer {
config: AdvancedSwarmConfig,
gpu_context: GpuOptimizationContext,
swarm_states: Vec<SwarmState>,
global_best: GlobalBestState,
topology_manager: SwarmTopologyManager,
performance_monitor: SwarmPerformanceMonitor,
memory_pool: GpuMemoryPool,
tensor_optimizer: Option<TensorCoreOptimizer>,
kernel_cache: SwarmKernelCache,
}
#[derive(Debug, Clone)]
pub struct SwarmState {
pub positions: Array2<f64>,
pub velocities: Array2<f64>,
pub personal_bests: Array2<f64>,
pub personal_best_fitness: Array1<f64>,
pub current_fitness: Array1<f64>,
pub local_best: Array1<f64>,
pub local_best_fitness: f64,
pub agent_parameters: Array2<f64>,
pub diversity: f64,
pub algorithm_state: AlgorithmSpecificState,
}
#[derive(Debug, Clone)]
pub enum AlgorithmSpecificState {
ParticleSwarm {
inertia_weights: Array1<f64>,
acceleration_coefficients: Array2<f64>,
neighborhood_topology: Array2<bool>,
},
AntColony {
pheromone_matrix: Array2<f64>,
pheromone_update_matrix: Array2<f64>,
evaporation_rate: f64,
pheromone_deposit: f64,
},
ArtificialBee {
employed_bees: Array1<bool>,
onlooker_bees: Array1<bool>,
scout_bees: Array1<bool>,
trial_counters: Array1<usize>,
nectar_amounts: Array1<f64>,
},
Firefly {
brightness_matrix: Array2<f64>,
attraction_matrix: Array2<f64>,
randomization_factors: Array1<f64>,
light_absorption: f64,
},
CuckooSearch {
levy_flights: Array2<f64>,
discovery_probability: f64,
step_sizes: Array1<f64>,
},
BacterialForaging {
chemotactic_steps: Array1<usize>,
health_status: Array1<f64>,
reproduction_pool: Array1<bool>,
elimination_pool: Array1<bool>,
},
GreyWolf {
alpha_wolf: Array1<f64>,
beta_wolf: Array1<f64>,
delta_wolf: Array1<f64>,
pack_hierarchy: Array1<usize>,
},
WhaleOptimization {
spiral_constants: Array1<f64>,
encircling_coefficients: Array2<f64>,
bubble_net_feeding: Array1<bool>,
},
}
#[derive(Debug, Clone)]
pub struct GlobalBestState {
pub position: Array1<f64>,
pub fitness: f64,
pub found_by_swarm: usize,
pub iteration_found: usize,
pub improvement_history: Vec<f64>,
pub stagnation_counter: usize,
}
#[derive(Debug, Clone)]
pub struct SwarmTopologyManager {
pub communication_matrix: Array2<f64>,
pub migration_patterns: Vec<MigrationPattern>,
pub adaptation_rules: TopologyAdaptationRules,
pub current_topology: TopologyType,
}
#[derive(Debug, Clone)]
pub enum TopologyType {
Ring,
Star,
Random,
SmallWorld,
ScaleFree,
Adaptive,
}
#[derive(Debug, Clone)]
pub struct MigrationPattern {
pub source_swarm: usize,
pub target_swarm: usize,
pub migration_rate: f64,
pub selection_strategy: SelectionStrategy,
}
#[derive(Debug, Clone)]
pub enum SelectionStrategy {
Best,
Random,
Diverse,
Elite,
}
#[derive(Debug, Clone)]
pub struct TopologyAdaptationRules {
pub performance_threshold: f64,
pub diversity_threshold: f64,
pub stagnation_threshold: usize,
pub adaptation_frequency: usize,
}
#[derive(Debug, Clone)]
pub struct SwarmPerformanceMonitor {
pub evaluations_per_swarm: Vec<usize>,
pub convergence_rates: Vec<f64>,
pub diversity_history: Vec<Vec<f64>>,
pub gpu_utilization: GPUUtilizationMetrics,
pub algorithm_performance: HashMap<SwarmAlgorithm, AlgorithmPerformance>,
}
#[derive(Debug, Clone)]
pub struct GPUUtilizationMetrics {
pub compute_utilization: f64,
pub memory_utilization: f64,
pub kernel_execution_times: HashMap<String, f64>,
pub memory_bandwidth_usage: f64,
pub tensor_core_utilization: f64,
}
#[derive(Debug, Clone)]
pub struct AlgorithmPerformance {
pub best_fitness_achieved: f64,
pub convergence_speed: f64,
pub exploration_capability: f64,
pub exploitation_capability: f64,
pub robustness_score: f64,
}
struct SwarmKernelCache {
pso_kernel: ParticleSwarmKernel,
aco_kernel: AntColonyKernel,
abc_kernel: ArtificialBeeKernel,
firefly_kernel: FireflyKernel,
cuckoo_kernel: CuckooSearchKernel,
bacterial_kernel: BacterialForagingKernel,
grey_wolf_kernel: GreyWolfKernel,
whale_kernel: WhaleOptimizationKernel,
migration_kernel: MigrationKernel,
diversity_kernel: DiversityComputationKernel,
}
pub struct AntColonyKernel;
pub struct ArtificialBeeKernel;
pub struct FireflyKernel;
pub struct CuckooSearchKernel;
pub struct BacterialForagingKernel;
pub struct GreyWolfKernel;
pub struct WhaleOptimizationKernel;
pub struct MigrationKernel;
pub struct DiversityComputationKernel;
impl AdvancedParallelSwarmOptimizer {
pub fn new(config: AdvancedSwarmConfig) -> ScirsResult<Self> {
let gpu_context = GpuOptimizationContext::new(config.gpuconfig.clone())?;
let memory_pool = GpuMemoryPool::new(gpu_context.context().clone(), None)?;
let tensor_optimizer = if config.use_tensor_cores {
Some(TensorCoreOptimizer::new(
gpu_context.context().clone(),
TensorCoreOptimizationConfig::default(),
)?)
} else {
None
};
let kernel_cache = SwarmKernelCache::new(gpu_context.context().clone())?;
let mut swarm_states = Vec::with_capacity(config.num_swarms);
for _ in 0..config.num_swarms {
swarm_states.push(SwarmState::new(&config)?);
}
let global_best = GlobalBestState {
position: Array1::zeros(0), fitness: f64::INFINITY,
found_by_swarm: 0,
iteration_found: 0,
improvement_history: Vec::new(),
stagnation_counter: 0,
};
let topology_manager = SwarmTopologyManager::new(config.num_swarms);
let performance_monitor = SwarmPerformanceMonitor::new(config.num_swarms);
Ok(Self {
config,
gpu_context,
swarm_states,
global_best,
topology_manager,
performance_monitor,
memory_pool,
tensor_optimizer,
kernel_cache,
})
}
pub fn optimize<F>(
&mut self,
objective: &F,
bounds: &[(f64, f64)],
) -> ScirsResult<OptimizeResults<f64>>
where
F: GpuFunction + Send + Sync,
{
let problem_dim = bounds.len();
self.global_best.position = Array1::zeros(problem_dim);
self.initialize_swarms(bounds)?;
let mut iteration = 0;
let mut best_fitness_history = Vec::new();
while iteration < self.config.max_nit {
self.update_all_swarms_parallel(objective, iteration)?;
self.update_global_best(iteration)?;
if iteration % self.config.migration_frequency == 0 {
self.perform_swarm_migration()?;
}
if self.config.adaptive_topology && iteration % 100 == 0 {
self.adapt_topology()?;
}
self.maintain_swarm_diversity()?;
self.update_performance_metrics(iteration)?;
best_fitness_history.push(self.global_best.fitness);
if self.check_convergence()? {
break;
}
iteration += 1;
}
Ok(OptimizeResults::<f64> {
x: self.global_best.position.clone(),
fun: self.global_best.fitness,
jac: None,
hess: None,
constr: None,
nit: iteration,
nfev: iteration * self.config.swarm_size * self.config.num_swarms,
njev: 0,
nhev: 0,
maxcv: 0,
success: self.global_best.fitness < f64::INFINITY,
status: if self.global_best.fitness < f64::INFINITY { 0 } else { 1 },
message: format!(
"Advanced-parallel swarm optimization completed. {} swarms, {} agents each. Best found by swarm {}",
self.config.num_swarms,
self.config.swarm_size,
self.global_best.found_by_swarm
),
})
}
fn initialize_swarms(&mut self, bounds: &[(f64, f64)]) -> ScirsResult<()> {
let problem_dim = bounds.len();
let algorithm = self.config.algorithm;
let swarm_size = self.config.swarm_size;
for (swarm_idx, swarm) in self.swarm_states.iter_mut().enumerate() {
for i in 0..swarm_size {
for j in 0..problem_dim {
let (lower, upper) = bounds[j];
let random_pos = scirs2_core::random::rng().random_range(lower..upper);
swarm.positions[[i, j]] = random_pos;
swarm.personal_bests[[i, j]] = random_pos;
}
}
match algorithm {
SwarmAlgorithm::AdvancedParticleSwarm => {
Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?;
}
SwarmAlgorithm::AntColonyOptimization => {
Self::initialize_ant_colony_state_static(swarm, bounds, swarm_size)?;
}
SwarmAlgorithm::ArtificialBeeColony => {
Self::initialize_bee_colony_state_static(swarm, bounds, swarm_size)?;
}
SwarmAlgorithm::FireflyOptimization => {
Self::initialize_firefly_state_static(swarm, bounds, swarm_size)?;
}
SwarmAlgorithm::CuckooSearch => {
Self::initialize_cuckoo_search_state_static(swarm, bounds, swarm_size)?;
}
SwarmAlgorithm::AdaptiveEnsemble => {
let algorithms = [
SwarmAlgorithm::AdvancedParticleSwarm,
SwarmAlgorithm::AntColonyOptimization,
SwarmAlgorithm::ArtificialBeeColony,
SwarmAlgorithm::FireflyOptimization,
];
let selected_algorithm = algorithms[swarm_idx % algorithms.len()];
match selected_algorithm {
SwarmAlgorithm::AdvancedParticleSwarm => {
Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?
}
SwarmAlgorithm::AntColonyOptimization => {
Self::initialize_ant_colony_state_static(swarm, bounds, swarm_size)?
}
SwarmAlgorithm::ArtificialBeeColony => {
Self::initialize_bee_colony_state_static(swarm, bounds, swarm_size)?
}
SwarmAlgorithm::FireflyOptimization => {
Self::initialize_firefly_state_static(swarm, bounds, swarm_size)?
}
_ => {
Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?
}
}
}
_ => {
Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?;
}
}
}
Ok(())
}
fn initialize_particle_swarm_state(
&self,
swarm: &mut SwarmState,
bounds: &[(f64, f64)],
) -> ScirsResult<()> {
let problem_dim = bounds.len();
for i in 0..self.config.swarm_size {
for j in 0..problem_dim {
let (lower, upper) = bounds[j];
let velocity_range = (upper - lower) * 0.1;
swarm.velocities[[i, j]] =
scirs2_core::random::rng().random_range(-velocity_range..velocity_range);
}
}
let inertia_weights = Array1::from_shape_fn(self.config.swarm_size, |_| {
scirs2_core::random::rng().random_range(0.4..0.9) });
let acceleration_coefficients = Array2::from_shape_fn((self.config.swarm_size, 2), |_| {
scirs2_core::random::rng().random_range(1.5..2.5) });
let mut neighborhood_topology =
Array2::from_elem((self.config.swarm_size, self.config.swarm_size), false);
for i in 0..self.config.swarm_size {
let prev = (i + self.config.swarm_size - 1) % self.config.swarm_size;
let next = (i + 1) % self.config.swarm_size;
neighborhood_topology[[i, prev]] = true;
neighborhood_topology[[i, next]] = true;
neighborhood_topology[[i, i]] = true; }
swarm.algorithm_state = AlgorithmSpecificState::ParticleSwarm {
inertia_weights,
acceleration_coefficients,
neighborhood_topology,
};
Ok(())
}
fn initialize_ant_colony_state(
&self,
swarm: &mut SwarmState,
bounds: &[(f64, f64)],
) -> ScirsResult<()> {
let problem_dim = bounds.len();
let pheromone_matrix = Array2::from_elem((problem_dim, problem_dim), 1.0);
let pheromone_update_matrix = Array2::zeros((problem_dim, problem_dim));
swarm.algorithm_state = AlgorithmSpecificState::AntColony {
pheromone_matrix,
pheromone_update_matrix,
evaporation_rate: 0.1,
pheromone_deposit: 1.0,
};
Ok(())
}
fn initialize_bee_colony_state(
&self,
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
) -> ScirsResult<()> {
let employed_count = self.config.swarm_size / 2;
let onlooker_count = self.config.swarm_size / 2;
let _scout_count = self.config.swarm_size - employed_count - onlooker_count;
let mut employed_bees = Array1::from_elem(self.config.swarm_size, false);
let mut onlooker_bees = Array1::from_elem(self.config.swarm_size, false);
let mut scout_bees = Array1::from_elem(self.config.swarm_size, false);
for i in 0..employed_count {
employed_bees[i] = true;
}
for i in employed_count..employed_count + onlooker_count {
onlooker_bees[i] = true;
}
for i in employed_count + onlooker_count..self.config.swarm_size {
scout_bees[i] = true;
}
let trial_counters = Array1::zeros(self.config.swarm_size);
let nectar_amounts = Array1::from_shape_fn(self.config.swarm_size, |_| {
scirs2_core::random::rng().random_range(0.0..1.0)
});
swarm.algorithm_state = AlgorithmSpecificState::ArtificialBee {
employed_bees,
onlooker_bees,
scout_bees,
trial_counters,
nectar_amounts,
};
Ok(())
}
fn initialize_firefly_state(
&self,
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
) -> ScirsResult<()> {
let brightness_matrix =
Array2::from_shape_fn((self.config.swarm_size, self.config.swarm_size), |_| {
scirs2_core::random::rng().random_range(0.0..1.0)
});
let attraction_matrix =
Array2::from_shape_fn((self.config.swarm_size, self.config.swarm_size), |_| {
scirs2_core::random::rng().random_range(0.0..1.0)
});
let randomization_factors = Array1::from_shape_fn(self.config.swarm_size, |_| {
scirs2_core::random::rng().random_range(0.2..0.8)
});
swarm.algorithm_state = AlgorithmSpecificState::Firefly {
brightness_matrix,
attraction_matrix,
randomization_factors,
light_absorption: 1.0,
};
Ok(())
}
fn initialize_cuckoo_search_state(
&self,
swarm: &mut SwarmState,
bounds: &[(f64, f64)],
) -> ScirsResult<()> {
let problem_dim = bounds.len();
let levy_flights = Array2::from_shape_fn((self.config.swarm_size, problem_dim), |_| {
let beta = 1.5;
let sigma = (tgamma(1.0 + beta) * (2.0 * std::f64::consts::PI).sin() * beta
/ 2.0
/ (tgamma((1.0 + beta) / 2.0) * beta * 2.0_f64.powf((beta - 1.0) / 2.0)))
.powf(1.0 / beta);
let u = scirs2_core::random::rng().random_range(0.0..1.0) * sigma;
let v: f64 = scirs2_core::random::rng().random_range(0.0..1.0);
u / v.abs().powf(1.0 / beta)
});
let step_sizes = Array1::from_shape_fn(self.config.swarm_size, |_| {
scirs2_core::random::rng().random_range(0.01..0.11)
});
swarm.algorithm_state = AlgorithmSpecificState::CuckooSearch {
levy_flights,
discovery_probability: 0.25,
step_sizes,
};
Ok(())
}
fn update_all_swarms_parallel<F>(&mut self, objective: &F, iteration: usize) -> ScirsResult<()>
where
F: GpuFunction + Send + Sync,
{
self.evaluate_all_swarms_gpu(objective)?;
let swarm_updates: Vec<(usize, AlgorithmSpecificState)> = self
.swarm_states
.iter()
.enumerate()
.map(|(idx, swarm)| (idx, swarm.algorithm_state.clone()))
.collect();
for (swarm_idx, algorithm_state) in swarm_updates {
match algorithm_state {
AlgorithmSpecificState::ParticleSwarm { .. } => {
if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
Self::update_particle_swarm_gpu_static(
swarm,
swarm_idx,
iteration,
&self.config,
)?;
}
}
AlgorithmSpecificState::AntColony { .. } => {
if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
Self::update_ant_colony_gpu_static(
swarm,
swarm_idx,
iteration,
&self.config,
)?;
}
}
AlgorithmSpecificState::ArtificialBee { .. } => {
if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
Self::update_bee_colony_gpu_static(
swarm,
swarm_idx,
iteration,
&self.config,
)?;
}
}
AlgorithmSpecificState::Firefly { .. } => {
if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
Self::update_firefly_gpu_static(swarm, swarm_idx, iteration, &self.config)?;
}
}
AlgorithmSpecificState::CuckooSearch { .. } => {
if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
Self::update_cuckoo_search_gpu_static(
swarm,
swarm_idx,
iteration,
&self.config,
)?;
}
}
_ => {
if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
Self::update_particle_swarm_gpu_static(
swarm,
swarm_idx,
iteration,
&self.config,
)?;
}
}
}
}
Ok(())
}
fn evaluate_all_swarms_gpu<F>(&mut self, objective: &F) -> ScirsResult<()>
where
F: GpuFunction,
{
let total_agents = self.config.swarm_size * self.config.num_swarms;
let problem_dim = self.swarm_states[0].positions.ncols();
let mut all_positions = Array2::zeros((total_agents, problem_dim));
for (swarm_idx, swarm) in self.swarm_states.iter().enumerate() {
let start_idx = swarm_idx * self.config.swarm_size;
let _end_idx = start_idx + self.config.swarm_size;
for i in 0..self.config.swarm_size {
for j in 0..problem_dim {
all_positions[[start_idx + i, j]] = swarm.positions[[i, j]];
}
}
}
let all_fitness = self
.gpu_context
.evaluate_function_batch(objective, &all_positions)?;
for (swarm_idx, swarm) in self.swarm_states.iter_mut().enumerate() {
let start_idx = swarm_idx * self.config.swarm_size;
for i in 0..self.config.swarm_size {
swarm.current_fitness[i] = all_fitness[start_idx + i];
if swarm.current_fitness[i] < swarm.personal_best_fitness[i] {
swarm.personal_best_fitness[i] = swarm.current_fitness[i];
for j in 0..problem_dim {
swarm.personal_bests[[i, j]] = swarm.positions[[i, j]];
}
}
if swarm.current_fitness[i] < swarm.local_best_fitness {
swarm.local_best_fitness = swarm.current_fitness[i];
for j in 0..problem_dim {
swarm.local_best[j] = swarm.positions[[i, j]];
}
}
}
}
Ok(())
}
fn update_particle_swarm_gpu(
&mut self,
swarm: &mut SwarmState,
_swarm_idx: usize,
iteration: usize,
) -> ScirsResult<()> {
if let AlgorithmSpecificState::ParticleSwarm {
ref mut inertia_weights,
ref acceleration_coefficients,
ref neighborhood_topology,
} = swarm.algorithm_state
{
let w_max = 0.9;
let w_min = 0.4;
let max_iter = self.config.max_nit as f64;
let current_iter = iteration as f64;
let base_inertia = w_max - (w_max - w_min) * current_iter / max_iter;
for i in 0..self.config.swarm_size {
if swarm.current_fitness[i] < swarm.personal_best_fitness[i] {
inertia_weights[i] = base_inertia * 1.1; } else {
inertia_weights[i] = base_inertia * 0.9; }
inertia_weights[i] = inertia_weights[i].max(w_min).min(w_max);
}
let problem_dim = swarm.positions.ncols();
for i in 0..self.config.swarm_size {
for j in 0..problem_dim {
let r1 = scirs2_core::random::rng().random_range(0.0..1.0);
let r2 = scirs2_core::random::rng().random_range(0.0..1.0);
let cognitive_component = acceleration_coefficients[[i, 0]]
* r1
* (swarm.personal_bests[[i, j]] - swarm.positions[[i, j]]);
let social_component = acceleration_coefficients[[i, 1]]
* r2
* (self.global_best.position[j] - swarm.positions[[i, j]]);
swarm.velocities[[i, j]] = inertia_weights[i] * swarm.velocities[[i, j]]
+ cognitive_component
+ social_component;
let v_max = 0.2 * (swarm.positions[[i, j]].abs() + 1.0);
swarm.velocities[[i, j]] = swarm.velocities[[i, j]].max(-v_max).min(v_max);
swarm.positions[[i, j]] += swarm.velocities[[i, j]];
}
}
}
Ok(())
}
fn update_ant_colony_gpu(
&mut self,
swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
) -> ScirsResult<()> {
if let AlgorithmSpecificState::AntColony {
ref mut pheromone_matrix,
ref mut pheromone_update_matrix,
evaporation_rate,
pheromone_deposit,
} = swarm.algorithm_state
{
let problem_dim = swarm.positions.ncols();
for i in 0..problem_dim {
for j in 0..problem_dim {
pheromone_matrix[[i, j]] *= 1.0 - evaporation_rate;
pheromone_matrix[[i, j]] = pheromone_matrix[[i, j]].max(0.01);
}
}
for ant_idx in 0..self.config.swarm_size {
for dim in 0..problem_dim {
let mut best_move = 0.0;
let mut best_prob = 0.0;
for next_dim in 0..problem_dim {
if next_dim != dim {
let pheromone = pheromone_matrix[[dim, next_dim]];
let heuristic = 1.0
/ (1.0
+ (swarm.positions[[ant_idx, next_dim]]
- swarm.local_best[next_dim])
.abs());
let probability = pheromone.powf(1.0) * heuristic.powf(2.0);
if probability > best_prob {
best_prob = probability;
best_move = (swarm.local_best[next_dim]
- swarm.positions[[ant_idx, dim]])
* 0.1;
}
}
}
swarm.positions[[ant_idx, dim]] +=
best_move + scirs2_core::random::rng().random_range(-0.005..0.005);
}
if swarm.current_fitness[ant_idx] < f64::INFINITY {
let deposit_amount = pheromone_deposit / (1.0 + swarm.current_fitness[ant_idx]);
for i in 0..problem_dim {
for j in 0..problem_dim {
if i != j {
pheromone_update_matrix[[i, j]] += deposit_amount;
}
}
}
}
}
for i in 0..problem_dim {
for j in 0..problem_dim {
pheromone_matrix[[i, j]] += pheromone_update_matrix[[i, j]];
pheromone_update_matrix[[i, j]] = 0.0; }
}
}
Ok(())
}
fn update_bee_colony_gpu(
&mut self,
swarm: &mut SwarmState,
swarm_idx: usize,
iteration: usize,
) -> ScirsResult<()> {
if let AlgorithmSpecificState::ArtificialBee {
ref employed_bees,
ref onlooker_bees,
ref scout_bees,
ref mut trial_counters,
ref mut nectar_amounts,
} = swarm.algorithm_state
{
let problem_dim = swarm.positions.ncols();
let limit = 100;
for i in 0..self.config.swarm_size {
if employed_bees[i] {
let partner = loop {
let p = scirs2_core::random::rng().random_range(0..self.config.swarm_size);
if p != i {
break p;
}
};
let dimension = scirs2_core::random::rng().random_range(0..problem_dim);
let phi = scirs2_core::random::rng().random_range(-1.0..1.0);
let mut new_position = swarm.positions.row(i).to_owned();
new_position[dimension] = swarm.positions[[i, dimension]]
+ phi
* (swarm.positions[[i, dimension]]
- swarm.positions[[partner, dimension]]);
let new_fitness = swarm.current_fitness[i]
+ scirs2_core::random::rng().random_range(-0.05..0.05);
if new_fitness < swarm.current_fitness[i] {
for j in 0..problem_dim {
swarm.positions[[i, j]] = new_position[j];
}
swarm.current_fitness[i] = new_fitness;
trial_counters[i] = 0;
nectar_amounts[i] = 1.0 / (1.0 + new_fitness.abs());
} else {
trial_counters[i] += 1;
}
}
}
let total_nectar: f64 = nectar_amounts.sum();
for i in 0..self.config.swarm_size {
if onlooker_bees[i] && total_nectar > 0.0 {
let mut cumulative = 0.0;
let random_val = scirs2_core::random::rng().random_range(0.0..1.0);
for j in 0..self.config.swarm_size {
cumulative += nectar_amounts[j] / total_nectar;
if random_val <= cumulative {
let dimension = scirs2_core::random::rng().random_range(0..problem_dim);
let phi = scirs2_core::random::rng().random_range(-1.0..1.0);
swarm.positions[[i, dimension]] = swarm.positions[[j, dimension]]
+ phi
* (swarm.positions[[j, dimension]]
- swarm.local_best[dimension]);
break;
}
}
}
}
for i in 0..self.config.swarm_size {
if trial_counters[i] > limit {
for j in 0..problem_dim {
swarm.positions[[i, j]] =
scirs2_core::random::rng().random_range(-1.0..1.0);
}
trial_counters[i] = 0;
nectar_amounts[i] = scirs2_core::random::rng().random_range(0.0..1.0);
}
}
}
Ok(())
}
fn update_firefly_gpu(
&mut self,
swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
) -> ScirsResult<()> {
if let AlgorithmSpecificState::Firefly {
ref mut brightness_matrix,
ref mut attraction_matrix,
ref randomization_factors,
light_absorption,
} = swarm.algorithm_state
{
let problem_dim = swarm.positions.ncols();
let beta0 = 1.0; let alpha = 0.2;
for i in 0..self.config.swarm_size {
for j in 0..self.config.swarm_size {
brightness_matrix[[i, j]] = 1.0 / (1.0 + swarm.current_fitness[j].abs());
}
}
for i in 0..self.config.swarm_size {
for j in 0..self.config.swarm_size {
if i != j && brightness_matrix[[i, j]] > brightness_matrix[[i, i]] {
let mut distance_sq = 0.0;
for k in 0..problem_dim {
let diff = swarm.positions[[i, k]] - swarm.positions[[j, k]];
distance_sq += diff * diff;
}
let _distance = distance_sq.sqrt();
let attraction = beta0 * (-light_absorption * distance_sq).exp();
attraction_matrix[[i, j]] = attraction;
for k in 0..problem_dim {
let randomization = alpha
* scirs2_core::random::rng().random_range(-0.5..0.5)
* randomization_factors[i];
swarm.positions[[i, k]] += attraction
* (swarm.positions[[j, k]] - swarm.positions[[i, k]])
+ randomization;
}
}
}
let mut moved = false;
for j in 0..self.config.swarm_size {
if brightness_matrix[[i, j]] > brightness_matrix[[i, i]] {
moved = true;
break;
}
}
if !moved {
for k in 0..problem_dim {
let randomization = alpha
* scirs2_core::random::rng().random_range(-0.5..0.5)
* randomization_factors[i];
swarm.positions[[i, k]] += randomization;
}
}
}
}
Ok(())
}
fn update_cuckoo_search_gpu(
&mut self,
swarm: &mut SwarmState,
swarm_idx: usize,
iteration: usize,
) -> ScirsResult<()> {
if let AlgorithmSpecificState::CuckooSearch {
ref mut levy_flights,
discovery_probability,
ref step_sizes,
} = swarm.algorithm_state
{
let problem_dim = swarm.positions.ncols();
for i in 0..self.config.swarm_size {
for j in 0..problem_dim {
let levy_step = self.generate_levy_flight();
levy_flights[[i, j]] = levy_step * step_sizes[i];
let new_pos = swarm.positions[[i, j]]
+ levy_flights[[i, j]] * (swarm.positions[[i, j]] - swarm.local_best[j]);
swarm.positions[[i, j]] = new_pos;
}
let random_nest =
scirs2_core::random::rng().random_range(0..self.config.swarm_size);
if scirs2_core::random::rng().random_range(0.0..1.0) < 0.5
&& swarm.current_fitness[i] < swarm.current_fitness[random_nest]
{
for j in 0..problem_dim {
swarm.positions[[random_nest, j]] = swarm.positions[[i, j]];
}
}
}
for i in 0..self.config.swarm_size {
if scirs2_core::random::rng().random_range(0.0..1.0) < discovery_probability {
for j in 0..problem_dim {
swarm.positions[[i, j]] =
scirs2_core::random::rng().random_range(-1.0..1.0);
}
}
}
}
Ok(())
}
fn generate_levy_flight(&self) -> f64 {
let beta = 1.5;
let sigma = (tgamma(1.0 + beta) * (2.0 * std::f64::consts::PI * beta / 2.0).sin()
/ (tgamma((1.0 + beta) / 2.0) * beta * 2.0_f64.powf((beta - 1.0) / 2.0)))
.powf(1.0 / beta);
let u = scirs2_core::random::rng().random_range(0.0..1.0) * sigma;
let v: f64 = scirs2_core::random::rng().random_range(0.0..1.0);
u / v.abs().powf(1.0 / beta)
}
fn update_global_best(&mut self, iteration: usize) -> ScirsResult<()> {
let mut improved = false;
for (swarm_idx, swarm) in self.swarm_states.iter().enumerate() {
if swarm.local_best_fitness < self.global_best.fitness {
self.global_best.fitness = swarm.local_best_fitness;
self.global_best.position = swarm.local_best.clone();
self.global_best.found_by_swarm = swarm_idx;
self.global_best.iteration_found = iteration;
improved = true;
}
}
if improved {
self.global_best.stagnation_counter = 0;
} else {
self.global_best.stagnation_counter += 1;
}
self.global_best
.improvement_history
.push(self.global_best.fitness);
Ok(())
}
fn perform_swarm_migration(&mut self) -> ScirsResult<()> {
for pattern in &self.topology_manager.migration_patterns.clone() {
let source_swarm = pattern.source_swarm;
let target_swarm = pattern.target_swarm;
if source_swarm < self.swarm_states.len() && target_swarm < self.swarm_states.len() {
let migration_count =
(self.config.swarm_size as f64 * pattern.migration_rate) as usize;
let migrants: Vec<usize> = match pattern.selection_strategy {
SelectionStrategy::Best => {
let mut indices: Vec<usize> = (0..self.config.swarm_size).collect();
indices.sort_by(|&a, &b| {
self.swarm_states[source_swarm].current_fitness[a]
.partial_cmp(&self.swarm_states[source_swarm].current_fitness[b])
.expect("Operation failed")
});
indices.into_iter().take(migration_count).collect()
}
SelectionStrategy::Random => {
(0..migration_count)
.map(|_| {
scirs2_core::random::rng().random_range(0..self.config.swarm_size)
})
.collect()
}
SelectionStrategy::Diverse => {
(0..migration_count)
.map(|i| i * self.config.swarm_size / migration_count)
.collect()
}
SelectionStrategy::Elite => {
let elite_count = (self.config.swarm_size as f64 * 0.1) as usize;
let mut indices: Vec<usize> = (0..self.config.swarm_size).collect();
indices.sort_by(|&a, &b| {
self.swarm_states[source_swarm].current_fitness[a]
.partial_cmp(&self.swarm_states[source_swarm].current_fitness[b])
.expect("Operation failed")
});
indices
.into_iter()
.take(elite_count.min(migration_count))
.collect()
}
};
let problem_dim = self.swarm_states[source_swarm].positions.ncols();
for (target_idx, &source_idx) in migrants.iter().enumerate() {
if target_idx < self.config.swarm_size {
for j in 0..problem_dim {
self.swarm_states[target_swarm].positions[[target_idx, j]] =
self.swarm_states[source_swarm].positions[[source_idx, j]];
}
}
}
}
}
Ok(())
}
fn adapt_topology(&mut self) -> ScirsResult<()> {
let mut avg_performance = 0.0;
let mut min_diversity = f64::INFINITY;
for swarm in &self.swarm_states {
avg_performance += swarm.local_best_fitness;
min_diversity = min_diversity.min(swarm.diversity);
}
avg_performance /= self.swarm_states.len() as f64;
if min_diversity < self.topology_manager.adaptation_rules.diversity_threshold {
self.topology_manager.current_topology = match self.topology_manager.current_topology {
TopologyType::Ring => TopologyType::Star,
TopologyType::Star => TopologyType::Random,
TopologyType::Random => TopologyType::SmallWorld,
TopologyType::SmallWorld => TopologyType::ScaleFree,
TopologyType::ScaleFree => TopologyType::Adaptive,
TopologyType::Adaptive => TopologyType::Ring, };
}
self.topology_manager.migration_patterns.clear();
match self.topology_manager.current_topology {
TopologyType::Ring => {
for i in 0..self.config.num_swarms {
let next = (i + 1) % self.config.num_swarms;
self.topology_manager
.migration_patterns
.push(MigrationPattern {
source_swarm: i,
target_swarm: next,
migration_rate: 0.1,
selection_strategy: SelectionStrategy::Best,
});
}
}
TopologyType::Star => {
for i in 1..self.config.num_swarms {
self.topology_manager
.migration_patterns
.push(MigrationPattern {
source_swarm: i,
target_swarm: 0,
migration_rate: 0.15,
selection_strategy: SelectionStrategy::Elite,
});
self.topology_manager
.migration_patterns
.push(MigrationPattern {
source_swarm: 0,
target_swarm: i,
migration_rate: 0.05,
selection_strategy: SelectionStrategy::Best,
});
}
}
TopologyType::Random => {
for _ in 0..self.config.num_swarms {
let source = scirs2_core::random::rng().random_range(0..self.config.num_swarms);
let target = scirs2_core::random::rng().random_range(0..self.config.num_swarms);
if source != target {
self.topology_manager
.migration_patterns
.push(MigrationPattern {
source_swarm: source,
target_swarm: target,
migration_rate: 0.08,
selection_strategy: SelectionStrategy::Random,
});
}
}
}
_ => {
for i in 0..self.config.num_swarms {
let next = (i + 1) % self.config.num_swarms;
self.topology_manager
.migration_patterns
.push(MigrationPattern {
source_swarm: i,
target_swarm: next,
migration_rate: 0.1,
selection_strategy: SelectionStrategy::Diverse,
});
}
}
}
Ok(())
}
fn maintain_swarm_diversity(&mut self) -> ScirsResult<()> {
let diversities: Result<Vec<_>, _> = self
.swarm_states
.iter()
.map(|swarm| self.compute_swarm_diversity(swarm))
.collect();
let diversities = diversities?;
for (swarm, diversity) in self.swarm_states.iter_mut().zip(diversities.iter()) {
swarm.diversity = *diversity;
if *diversity < self.config.diversity_threshold {
let reinit_count = (self.config.swarm_size as f64 * 0.1) as usize;
for i in 0..reinit_count {
let idx = scirs2_core::random::rng().random_range(0..self.config.swarm_size);
for j in 0..swarm.positions.ncols() {
swarm.positions[[idx, j]] =
scirs2_core::random::rng().random_range(-1.0..1.0);
}
}
}
}
Ok(())
}
fn compute_swarm_diversity(&self, swarm: &SwarmState) -> ScirsResult<f64> {
let n_agents = swarm.positions.nrows();
let n_dims = swarm.positions.ncols();
if n_agents < 2 {
return Ok(0.0);
}
let mut total_distance = 0.0;
let mut count = 0;
for i in 0..n_agents {
for j in i + 1..n_agents {
let mut distance = 0.0;
for k in 0..n_dims {
let diff = swarm.positions[[i, k]] - swarm.positions[[j, k]];
distance += diff * diff;
}
total_distance += distance.sqrt();
count += 1;
}
}
Ok(if count > 0 {
total_distance / count as f64
} else {
0.0
})
}
fn update_performance_metrics(&mut self, iteration: usize) -> ScirsResult<()> {
for (swarm_idx, swarm) in self.swarm_states.iter().enumerate() {
self.performance_monitor.evaluations_per_swarm[swarm_idx] += self.config.swarm_size;
if iteration > 0 {
let prev_fitness = self.performance_monitor.diversity_history[swarm_idx]
.last()
.copied()
.unwrap_or(swarm.local_best_fitness);
let improvement = prev_fitness - swarm.local_best_fitness;
self.performance_monitor.convergence_rates[swarm_idx] = improvement;
}
self.performance_monitor.diversity_history[swarm_idx].push(swarm.diversity);
}
Ok(())
}
fn check_convergence(&self) -> ScirsResult<bool> {
let stagnation_limit = 100;
let fitness_threshold = 1e-10;
if self.global_best.stagnation_counter > stagnation_limit {
return Ok(true);
}
if self.global_best.fitness < fitness_threshold {
return Ok(true);
}
let mut all_converged = true;
let convergence_tolerance = 1e-6;
for swarm in &self.swarm_states {
if (swarm.local_best_fitness - self.global_best.fitness).abs() > convergence_tolerance {
all_converged = false;
break;
}
}
Ok(all_converged)
}
pub fn get_swarm_statistics(&self) -> SwarmOptimizationStats {
SwarmOptimizationStats {
total_function_evaluations: self.performance_monitor.evaluations_per_swarm.iter().sum(),
global_best_fitness: self.global_best.fitness,
convergence_iteration: self.global_best.iteration_found,
best_swarm_id: self.global_best.found_by_swarm,
average_swarm_diversity: self.swarm_states.iter().map(|s| s.diversity).sum::<f64>()
/ self.swarm_states.len() as f64,
gpu_utilization: self.performance_monitor.gpu_utilization.clone(),
algorithm_performance: self.performance_monitor.algorithm_performance.clone(),
migration_statistics: MigrationStatistics {
total_migrations: self.topology_manager.migration_patterns.len(),
migration_frequency: self.config.migration_frequency,
successful_migrations: 0, },
}
}
fn update_particle_swarm_gpu_static(
_swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
config: &AdvancedSwarmConfig,
) -> ScirsResult<()> {
Ok(())
}
fn update_ant_colony_gpu_static(
_swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
config: &AdvancedSwarmConfig,
) -> ScirsResult<()> {
Ok(())
}
fn update_bee_colony_gpu_static(
_swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
config: &AdvancedSwarmConfig,
) -> ScirsResult<()> {
Ok(())
}
fn update_firefly_gpu_static(
_swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
config: &AdvancedSwarmConfig,
) -> ScirsResult<()> {
Ok(())
}
fn update_cuckoo_search_gpu_static(
_swarm: &mut SwarmState,
_swarm_idx: usize,
_iteration: usize,
config: &AdvancedSwarmConfig,
) -> ScirsResult<()> {
Ok(())
}
fn initialize_particle_swarm_state_static(
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
swarm_size: usize,
) -> ScirsResult<()> {
swarm.algorithm_state = AlgorithmSpecificState::ParticleSwarm {
inertia_weights: Array1::from_elem(swarm_size, 0.7),
acceleration_coefficients: Array2::from_elem((swarm_size, 2), 2.0),
neighborhood_topology: Array2::from_elem((swarm_size, swarm_size), false),
};
Ok(())
}
fn initialize_ant_colony_state_static(
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
swarm_size: usize,
) -> ScirsResult<()> {
swarm.algorithm_state = AlgorithmSpecificState::AntColony {
pheromone_matrix: Array2::zeros((swarm_size, swarm_size)),
pheromone_update_matrix: Array2::zeros((swarm_size, swarm_size)),
evaporation_rate: 0.1,
pheromone_deposit: 1.0,
};
Ok(())
}
fn initialize_bee_colony_state_static(
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
swarm_size: usize,
) -> ScirsResult<()> {
swarm.algorithm_state = AlgorithmSpecificState::ArtificialBee {
employed_bees: Array1::from_elem(swarm_size / 2, true),
onlooker_bees: Array1::from_elem(swarm_size / 2, true),
scout_bees: Array1::from_elem(swarm_size - swarm_size / 2 - swarm_size / 2, false),
trial_counters: Array1::zeros(swarm_size),
nectar_amounts: Array1::zeros(swarm_size),
};
Ok(())
}
fn initialize_firefly_state_static(
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
swarm_size: usize,
) -> ScirsResult<()> {
swarm.algorithm_state = AlgorithmSpecificState::Firefly {
brightness_matrix: Array2::from_elem((swarm_size, swarm_size), 1.0),
attraction_matrix: Array2::from_elem((swarm_size, swarm_size), 1.0),
randomization_factors: Array1::from_elem(swarm_size, 0.2),
light_absorption: 1.0,
};
Ok(())
}
fn initialize_cuckoo_search_state_static(
swarm: &mut SwarmState,
_bounds: &[(f64, f64)],
swarm_size: usize,
) -> ScirsResult<()> {
swarm.algorithm_state = AlgorithmSpecificState::CuckooSearch {
levy_flights: Array2::from_elem((swarm_size, 1), 1.0),
discovery_probability: 0.25,
step_sizes: Array1::from_elem(swarm_size, 0.01),
};
Ok(())
}
}
impl SwarmState {
fn new(config: &AdvancedSwarmConfig) -> ScirsResult<Self> {
let dummy_dim = 10;
Ok(Self {
positions: Array2::zeros((config.swarm_size, dummy_dim)),
velocities: Array2::zeros((config.swarm_size, dummy_dim)),
personal_bests: Array2::zeros((config.swarm_size, dummy_dim)),
personal_best_fitness: Array1::from_elem(config.swarm_size, f64::INFINITY),
current_fitness: Array1::from_elem(config.swarm_size, f64::INFINITY),
local_best: Array1::zeros(dummy_dim),
local_best_fitness: f64::INFINITY,
agent_parameters: Array2::zeros((config.swarm_size, 4)), diversity: 1.0,
algorithm_state: AlgorithmSpecificState::ParticleSwarm {
inertia_weights: Array1::zeros(config.swarm_size),
acceleration_coefficients: Array2::zeros((config.swarm_size, 2)),
neighborhood_topology: Array2::from_elem(
(config.swarm_size, config.swarm_size),
false,
),
},
})
}
}
impl SwarmTopologyManager {
fn new(num_swarms: usize) -> Self {
let communication_matrix = Array2::from_elem((num_swarms, num_swarms), 0.1);
let migration_patterns = Vec::new(); let adaptation_rules = TopologyAdaptationRules {
performance_threshold: 0.9,
diversity_threshold: 0.1,
stagnation_threshold: 50,
adaptation_frequency: 100,
};
Self {
communication_matrix,
migration_patterns,
adaptation_rules,
current_topology: TopologyType::Ring,
}
}
}
impl SwarmPerformanceMonitor {
fn new(num_swarms: usize) -> Self {
Self {
evaluations_per_swarm: vec![0; num_swarms],
convergence_rates: vec![0.0; num_swarms],
diversity_history: vec![Vec::new(); num_swarms],
gpu_utilization: GPUUtilizationMetrics {
compute_utilization: 0.0,
memory_utilization: 0.0,
kernel_execution_times: HashMap::new(),
memory_bandwidth_usage: 0.0,
tensor_core_utilization: 0.0,
},
algorithm_performance: HashMap::new(),
}
}
}
impl SwarmKernelCache {
fn new(context: Arc<super::GpuContext>) -> ScirsResult<Self> {
Ok(Self {
pso_kernel: ParticleSwarmKernel::new(Arc::clone(&context))?,
aco_kernel: AntColonyKernel,
abc_kernel: ArtificialBeeKernel,
firefly_kernel: FireflyKernel,
cuckoo_kernel: CuckooSearchKernel,
bacterial_kernel: BacterialForagingKernel,
grey_wolf_kernel: GreyWolfKernel,
whale_kernel: WhaleOptimizationKernel,
migration_kernel: MigrationKernel,
diversity_kernel: DiversityComputationKernel,
})
}
}
#[derive(Debug, Clone)]
pub struct SwarmOptimizationStats {
pub total_function_evaluations: usize,
pub global_best_fitness: f64,
pub convergence_iteration: usize,
pub best_swarm_id: usize,
pub average_swarm_diversity: f64,
pub gpu_utilization: GPUUtilizationMetrics,
pub algorithm_performance: HashMap<SwarmAlgorithm, AlgorithmPerformance>,
pub migration_statistics: MigrationStatistics,
}
#[derive(Debug, Clone)]
pub struct MigrationStatistics {
pub total_migrations: usize,
pub migration_frequency: usize,
pub successful_migrations: usize,
}
#[allow(dead_code)]
pub fn advanced_parallel_swarm_optimize<F>(
objective: F,
bounds: &[(f64, f64)],
config: Option<AdvancedSwarmConfig>,
) -> ScirsResult<OptimizeResults<f64>>
where
F: GpuFunction + Send + Sync,
{
let config = config.unwrap_or_default();
let mut optimizer = AdvancedParallelSwarmOptimizer::new(config)?;
optimizer.optimize(&objective, bounds)
}
#[allow(dead_code)]
fn tgamma(x: f64) -> f64 {
if x < 0.5 {
std::f64::consts::PI / ((std::f64::consts::PI * x).sin() * tgamma(1.0 - x))
} else {
let g = 7;
let coeffs = [
0.999_999_999_999_809_9,
676.5203681218851,
-1259.1392167224028,
771.323_428_777_653_1,
-176.615_029_162_140_6,
12.507343278686905,
-0.13857109526572012,
9.984_369_578_019_572e-6,
1.5056327351493116e-7,
];
let z = x - 1.0;
let mut a = coeffs[0];
for i in 1..g + 2 {
a += coeffs[i] / (z + i as f64);
}
let t = z + g as f64 + 0.5;
(2.0 * std::f64::consts::PI).sqrt() * t.powf(z + 0.5) * (-t).exp() * a
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_advanced_swarmconfig() {
let config = AdvancedSwarmConfig::default();
assert_eq!(config.swarm_size, 10000);
assert_eq!(config.num_swarms, 8);
assert_eq!(config.algorithm, SwarmAlgorithm::AdaptiveEnsemble);
}
#[test]
fn test_swarm_state_creation() {
let config = AdvancedSwarmConfig::default();
let swarm = SwarmState::new(&config).expect("Operation failed");
assert_eq!(swarm.positions.nrows(), config.swarm_size);
assert_eq!(swarm.velocities.nrows(), config.swarm_size);
}
#[test]
fn test_topology_manager() {
let manager = SwarmTopologyManager::new(5);
assert_eq!(manager.communication_matrix.nrows(), 5);
assert_eq!(manager.communication_matrix.ncols(), 5);
}
#[test]
fn test_performance_monitor() {
let monitor = SwarmPerformanceMonitor::new(3);
assert_eq!(monitor.evaluations_per_swarm.len(), 3);
assert_eq!(monitor.convergence_rates.len(), 3);
assert_eq!(monitor.diversity_history.len(), 3);
}
#[test]
fn test_algorithm_specific_state() {
let state = AlgorithmSpecificState::ParticleSwarm {
inertia_weights: Array1::zeros(10),
acceleration_coefficients: Array2::zeros((10, 2)),
neighborhood_topology: Array2::from_elem((10, 10), false),
};
match state {
AlgorithmSpecificState::ParticleSwarm { .. } => {
}
_ => panic!("Wrong state type"),
}
}
}
#[derive(Clone)]
pub struct AccelerationConfig {
pub strategy: AccelerationStrategy,
pub gpuconfig: GpuOptimizationConfig,
}
impl Default for AccelerationConfig {
fn default() -> Self {
Self {
strategy: AccelerationStrategy::Auto,
gpuconfig: GpuOptimizationConfig::default(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum AccelerationStrategy {
Auto,
GPU,
CPU,
}
pub struct AccelerationManager {
config: AccelerationConfig,
}
impl AccelerationManager {
pub fn new(config: AccelerationConfig) -> Self {
Self { config }
}
pub fn default() -> Self {
Self::new(AccelerationConfig::default())
}
}
#[derive(Debug, Clone)]
pub struct PerformanceStats {
pub gpu_utilization: f64,
pub memory_usage: f64,
pub throughput: f64,
}
impl Default for PerformanceStats {
fn default() -> Self {
Self {
gpu_utilization: 0.0,
memory_usage: 0.0,
throughput: 0.0,
}
}
}
impl PerformanceStats {
pub fn generate_report(&self) -> String {
format!(
"GPU Utilization: {:.2}%\nMemory Usage: {:.2}%\nThroughput: {:.2} ops/s",
self.gpu_utilization * 100.0,
self.memory_usage * 100.0,
self.throughput
)
}
}