1use crate::error::ScirsResult;
13use ndarray::{Array1, Array2};
14use rand::Rng;
15use std::collections::HashMap;
16use std::sync::Arc;
17
18use super::{
19 cuda_kernels::ParticleSwarmKernel,
20 memory_management::GpuMemoryPool,
21 tensor_core_optimization::{TensorCoreOptimizationConfig, TensorCoreOptimizer},
22 GpuFunction, GpuOptimizationConfig, GpuOptimizationContext,
23};
24use crate::result::OptimizeResults;
25
26#[derive(Debug, Clone, Copy, PartialEq)]
28pub enum SwarmAlgorithm {
29 AdvancedParticleSwarm,
31 AntColonyOptimization,
33 ArtificialBeeColony,
35 FireflyOptimization,
37 CuckooSearch,
39 HybridMultiSwarm,
41 BacterialForaging,
43 GreyWolfOptimization,
45 WhaleOptimization,
47 AdaptiveEnsemble,
49}
50
51#[derive(Clone)]
53pub struct AdvancedSwarmConfig {
54 pub algorithm: SwarmAlgorithm,
56 pub swarm_size: usize,
58 pub num_swarms: usize,
60 pub gpuconfig: GpuOptimizationConfig,
62 pub max_nit: usize,
64 pub diversity_threshold: f64,
66 pub elite_rate: f64,
68 pub migration_frequency: usize,
70 pub adaptive_topology: bool,
72 pub use_tensor_cores: bool,
74 pub mixed_precision: bool,
76 pub simd_level: SimdLevel,
78}
79
80#[derive(Debug, Clone, Copy, PartialEq)]
81pub enum SimdLevel {
82 None,
83 Basic,
84 Advanced,
85 Maximum,
86}
87
88impl Default for AdvancedSwarmConfig {
89 fn default() -> Self {
90 Self {
91 algorithm: SwarmAlgorithm::AdaptiveEnsemble,
92 swarm_size: 10000, num_swarms: 8, gpuconfig: GpuOptimizationConfig::default(),
95 max_nit: 1000,
96 diversity_threshold: 1e-6,
97 elite_rate: 0.1,
98 migration_frequency: 50,
99 adaptive_topology: true,
100 use_tensor_cores: true,
101 mixed_precision: true,
102 simd_level: SimdLevel::Advanced,
103 }
104 }
105}
106
107pub struct AdvancedParallelSwarmOptimizer {
109 config: AdvancedSwarmConfig,
110 gpu_context: GpuOptimizationContext,
111 swarm_states: Vec<SwarmState>,
112 global_best: GlobalBestState,
113 topology_manager: SwarmTopologyManager,
114 performance_monitor: SwarmPerformanceMonitor,
115 memory_pool: GpuMemoryPool,
116 tensor_optimizer: Option<TensorCoreOptimizer>,
117 kernel_cache: SwarmKernelCache,
118}
119
120#[derive(Debug, Clone)]
122pub struct SwarmState {
123 pub positions: Array2<f64>,
125 pub velocities: Array2<f64>,
127 pub personal_bests: Array2<f64>,
129 pub personal_best_fitness: Array1<f64>,
131 pub current_fitness: Array1<f64>,
133 pub local_best: Array1<f64>,
135 pub local_best_fitness: f64,
137 pub agent_parameters: Array2<f64>,
139 pub diversity: f64,
141 pub algorithm_state: AlgorithmSpecificState,
143}
144
145#[derive(Debug, Clone)]
147pub enum AlgorithmSpecificState {
148 ParticleSwarm {
149 inertia_weights: Array1<f64>,
150 acceleration_coefficients: Array2<f64>,
151 neighborhood_topology: Array2<bool>,
152 },
153 AntColony {
154 pheromone_matrix: Array2<f64>,
155 pheromone_update_matrix: Array2<f64>,
156 evaporation_rate: f64,
157 pheromone_deposit: f64,
158 },
159 ArtificialBee {
160 employed_bees: Array1<bool>,
161 onlooker_bees: Array1<bool>,
162 scout_bees: Array1<bool>,
163 trial_counters: Array1<usize>,
164 nectar_amounts: Array1<f64>,
165 },
166 Firefly {
167 brightness_matrix: Array2<f64>,
168 attraction_matrix: Array2<f64>,
169 randomization_factors: Array1<f64>,
170 light_absorption: f64,
171 },
172 CuckooSearch {
173 levy_flights: Array2<f64>,
174 discovery_probability: f64,
175 step_sizes: Array1<f64>,
176 },
177 BacterialForaging {
178 chemotactic_steps: Array1<usize>,
179 health_status: Array1<f64>,
180 reproduction_pool: Array1<bool>,
181 elimination_pool: Array1<bool>,
182 },
183 GreyWolf {
184 alpha_wolf: Array1<f64>,
185 beta_wolf: Array1<f64>,
186 delta_wolf: Array1<f64>,
187 pack_hierarchy: Array1<usize>,
188 },
189 WhaleOptimization {
190 spiral_constants: Array1<f64>,
191 encircling_coefficients: Array2<f64>,
192 bubble_net_feeding: Array1<bool>,
193 },
194}
195
196#[derive(Debug, Clone)]
198pub struct GlobalBestState {
199 pub position: Array1<f64>,
200 pub fitness: f64,
201 pub found_by_swarm: usize,
202 pub iteration_found: usize,
203 pub improvement_history: Vec<f64>,
204 pub stagnation_counter: usize,
205}
206
207#[derive(Debug, Clone)]
209pub struct SwarmTopologyManager {
210 pub communication_matrix: Array2<f64>,
212 pub migration_patterns: Vec<MigrationPattern>,
214 pub adaptation_rules: TopologyAdaptationRules,
216 pub current_topology: TopologyType,
218}
219
220#[derive(Debug, Clone)]
221pub enum TopologyType {
222 Ring,
223 Star,
224 Random,
225 SmallWorld,
226 ScaleFree,
227 Adaptive,
228}
229
230#[derive(Debug, Clone)]
231pub struct MigrationPattern {
232 pub source_swarm: usize,
233 pub target_swarm: usize,
234 pub migration_rate: f64,
235 pub selection_strategy: SelectionStrategy,
236}
237
238#[derive(Debug, Clone)]
239pub enum SelectionStrategy {
240 Best,
241 Random,
242 Diverse,
243 Elite,
244}
245
246#[derive(Debug, Clone)]
247pub struct TopologyAdaptationRules {
248 pub performance_threshold: f64,
249 pub diversity_threshold: f64,
250 pub stagnation_threshold: usize,
251 pub adaptation_frequency: usize,
252}
253
254#[derive(Debug, Clone)]
256pub struct SwarmPerformanceMonitor {
257 pub evaluations_per_swarm: Vec<usize>,
259 pub convergence_rates: Vec<f64>,
261 pub diversity_history: Vec<Vec<f64>>,
263 pub gpu_utilization: GPUUtilizationMetrics,
265 pub algorithm_performance: HashMap<SwarmAlgorithm, AlgorithmPerformance>,
267}
268
269#[derive(Debug, Clone)]
270pub struct GPUUtilizationMetrics {
271 pub compute_utilization: f64,
272 pub memory_utilization: f64,
273 pub kernel_execution_times: HashMap<String, f64>,
274 pub memory_bandwidth_usage: f64,
275 pub tensor_core_utilization: f64,
276}
277
278#[derive(Debug, Clone)]
279pub struct AlgorithmPerformance {
280 pub best_fitness_achieved: f64,
281 pub convergence_speed: f64,
282 pub exploration_capability: f64,
283 pub exploitation_capability: f64,
284 pub robustness_score: f64,
285}
286
287struct SwarmKernelCache {
289 pso_kernel: ParticleSwarmKernel,
290 aco_kernel: AntColonyKernel,
291 abc_kernel: ArtificialBeeKernel,
292 firefly_kernel: FireflyKernel,
293 cuckoo_kernel: CuckooSearchKernel,
294 bacterial_kernel: BacterialForagingKernel,
295 grey_wolf_kernel: GreyWolfKernel,
296 whale_kernel: WhaleOptimizationKernel,
297 migration_kernel: MigrationKernel,
298 diversity_kernel: DiversityComputationKernel,
299}
300
301pub struct AntColonyKernel;
303pub struct ArtificialBeeKernel;
304pub struct FireflyKernel;
305pub struct CuckooSearchKernel;
306pub struct BacterialForagingKernel;
307pub struct GreyWolfKernel;
308pub struct WhaleOptimizationKernel;
309pub struct MigrationKernel;
310pub struct DiversityComputationKernel;
311
312impl AdvancedParallelSwarmOptimizer {
313 pub fn new(config: AdvancedSwarmConfig) -> ScirsResult<Self> {
315 let gpu_context = GpuOptimizationContext::new(config.gpuconfig.clone())?;
316 let memory_pool = GpuMemoryPool::new(gpu_context.context().clone(), None)?;
317
318 let tensor_optimizer = if config.use_tensor_cores {
319 Some(TensorCoreOptimizer::new(
320 gpu_context.context().clone(),
321 TensorCoreOptimizationConfig::default(),
322 )?)
323 } else {
324 None
325 };
326
327 let kernel_cache = SwarmKernelCache::new(gpu_context.context().clone())?;
328
329 let mut swarm_states = Vec::with_capacity(config.num_swarms);
331 for _ in 0..config.num_swarms {
332 swarm_states.push(SwarmState::new(&config)?);
333 }
334
335 let global_best = GlobalBestState {
336 position: Array1::zeros(0), fitness: f64::INFINITY,
338 found_by_swarm: 0,
339 iteration_found: 0,
340 improvement_history: Vec::new(),
341 stagnation_counter: 0,
342 };
343
344 let topology_manager = SwarmTopologyManager::new(config.num_swarms);
345 let performance_monitor = SwarmPerformanceMonitor::new(config.num_swarms);
346
347 Ok(Self {
348 config,
349 gpu_context,
350 swarm_states,
351 global_best,
352 topology_manager,
353 performance_monitor,
354 memory_pool,
355 tensor_optimizer,
356 kernel_cache,
357 })
358 }
359
360 pub fn optimize<F>(
362 &mut self,
363 objective: &F,
364 bounds: &[(f64, f64)],
365 ) -> ScirsResult<OptimizeResults<f64>>
366 where
367 F: GpuFunction + Send + Sync,
368 {
369 let problem_dim = bounds.len();
370
371 self.global_best.position = Array1::zeros(problem_dim);
373
374 self.initialize_swarms(bounds)?;
376
377 let mut iteration = 0;
378 let mut best_fitness_history = Vec::new();
379
380 while iteration < self.config.max_nit {
381 self.update_all_swarms_parallel(objective, iteration)?;
383
384 self.update_global_best(iteration)?;
386
387 if iteration % self.config.migration_frequency == 0 {
389 self.perform_swarm_migration()?;
390 }
391
392 if self.config.adaptive_topology && iteration % 100 == 0 {
394 self.adapt_topology()?;
395 }
396
397 self.maintain_swarm_diversity()?;
399
400 self.update_performance_metrics(iteration)?;
402
403 best_fitness_history.push(self.global_best.fitness);
405
406 if self.check_convergence()? {
408 break;
409 }
410
411 iteration += 1;
412 }
413
414 Ok(OptimizeResults::<f64> {
415 x: self.global_best.position.clone(),
416 fun: self.global_best.fitness,
417 jac: None,
418 hess: None,
419 constr: None,
420 nit: iteration,
421 nfev: iteration * self.config.swarm_size * self.config.num_swarms,
422 njev: 0,
423 nhev: 0,
424 maxcv: 0,
425 success: self.global_best.fitness < f64::INFINITY,
426 status: if self.global_best.fitness < f64::INFINITY { 0 } else { 1 },
427 message: format!(
428 "Advanced-parallel swarm optimization completed. {} swarms, {} agents each. Best found by swarm {}",
429 self.config.num_swarms,
430 self.config.swarm_size,
431 self.global_best.found_by_swarm
432 ),
433 })
434 }
435
436 fn initialize_swarms(&mut self, bounds: &[(f64, f64)]) -> ScirsResult<()> {
437 let problem_dim = bounds.len();
438 let algorithm = self.config.algorithm.clone();
439 let swarm_size = self.config.swarm_size;
440
441 for (swarm_idx, swarm) in self.swarm_states.iter_mut().enumerate() {
442 for i in 0..swarm_size {
444 for j in 0..problem_dim {
445 let (lower, upper) = bounds[j];
446 let random_pos = rand::rng().random_range(lower..upper);
447 swarm.positions[[i, j]] = random_pos;
448 swarm.personal_bests[[i, j]] = random_pos;
449 }
450 }
451
452 match algorithm {
454 SwarmAlgorithm::AdvancedParticleSwarm => {
455 Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?;
456 }
457 SwarmAlgorithm::AntColonyOptimization => {
458 Self::initialize_ant_colony_state_static(swarm, bounds, swarm_size)?;
459 }
460 SwarmAlgorithm::ArtificialBeeColony => {
461 Self::initialize_bee_colony_state_static(swarm, bounds, swarm_size)?;
462 }
463 SwarmAlgorithm::FireflyOptimization => {
464 Self::initialize_firefly_state_static(swarm, bounds, swarm_size)?;
465 }
466 SwarmAlgorithm::CuckooSearch => {
467 Self::initialize_cuckoo_search_state_static(swarm, bounds, swarm_size)?;
468 }
469 SwarmAlgorithm::AdaptiveEnsemble => {
470 let algorithms = [
472 SwarmAlgorithm::AdvancedParticleSwarm,
473 SwarmAlgorithm::AntColonyOptimization,
474 SwarmAlgorithm::ArtificialBeeColony,
475 SwarmAlgorithm::FireflyOptimization,
476 ];
477 let selected_algorithm = algorithms[swarm_idx % algorithms.len()];
478 match selected_algorithm {
479 SwarmAlgorithm::AdvancedParticleSwarm => {
480 Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?
481 }
482 SwarmAlgorithm::AntColonyOptimization => {
483 Self::initialize_ant_colony_state_static(swarm, bounds, swarm_size)?
484 }
485 SwarmAlgorithm::ArtificialBeeColony => {
486 Self::initialize_bee_colony_state_static(swarm, bounds, swarm_size)?
487 }
488 SwarmAlgorithm::FireflyOptimization => {
489 Self::initialize_firefly_state_static(swarm, bounds, swarm_size)?
490 }
491 _ => {
492 Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?
493 }
494 }
495 }
496 _ => {
497 Self::initialize_particle_swarm_state_static(swarm, bounds, swarm_size)?;
498 }
499 }
500 }
501
502 Ok(())
503 }
504
505 fn initialize_particle_swarm_state(
506 &self,
507 swarm: &mut SwarmState,
508 bounds: &[(f64, f64)],
509 ) -> ScirsResult<()> {
510 let problem_dim = bounds.len();
511
512 for i in 0..self.config.swarm_size {
514 for j in 0..problem_dim {
515 let (lower, upper) = bounds[j];
516 let velocity_range = (upper - lower) * 0.1;
517 swarm.velocities[[i, j]] =
518 rand::rng().random_range(-velocity_range..velocity_range);
519 }
520 }
521
522 let inertia_weights = Array1::from_shape_fn(self.config.swarm_size, |_| {
524 rand::rng().random_range(0.4..0.9) });
526
527 let acceleration_coefficients = Array2::from_shape_fn((self.config.swarm_size, 2), |_| {
528 rand::rng().random_range(1.5..2.5) });
530
531 let mut neighborhood_topology =
533 Array2::from_elem((self.config.swarm_size, self.config.swarm_size), false);
534 for i in 0..self.config.swarm_size {
535 let prev = (i + self.config.swarm_size - 1) % self.config.swarm_size;
536 let next = (i + 1) % self.config.swarm_size;
537 neighborhood_topology[[i, prev]] = true;
538 neighborhood_topology[[i, next]] = true;
539 neighborhood_topology[[i, i]] = true; }
541
542 swarm.algorithm_state = AlgorithmSpecificState::ParticleSwarm {
543 inertia_weights,
544 acceleration_coefficients,
545 neighborhood_topology,
546 };
547
548 Ok(())
549 }
550
551 fn initialize_ant_colony_state(
552 &self,
553 swarm: &mut SwarmState,
554 bounds: &[(f64, f64)],
555 ) -> ScirsResult<()> {
556 let problem_dim = bounds.len();
557
558 let pheromone_matrix = Array2::from_elem((problem_dim, problem_dim), 1.0);
560 let pheromone_update_matrix = Array2::zeros((problem_dim, problem_dim));
561
562 swarm.algorithm_state = AlgorithmSpecificState::AntColony {
563 pheromone_matrix,
564 pheromone_update_matrix,
565 evaporation_rate: 0.1,
566 pheromone_deposit: 1.0,
567 };
568
569 Ok(())
570 }
571
572 fn initialize_bee_colony_state(
573 &self,
574 swarm: &mut SwarmState,
575 _bounds: &[(f64, f64)],
576 ) -> ScirsResult<()> {
577 let employed_count = self.config.swarm_size / 2;
578 let onlooker_count = self.config.swarm_size / 2;
579 let _scout_count = self.config.swarm_size - employed_count - onlooker_count;
580
581 let mut employed_bees = Array1::from_elem(self.config.swarm_size, false);
582 let mut onlooker_bees = Array1::from_elem(self.config.swarm_size, false);
583 let mut scout_bees = Array1::from_elem(self.config.swarm_size, false);
584
585 for i in 0..employed_count {
587 employed_bees[i] = true;
588 }
589 for i in employed_count..employed_count + onlooker_count {
590 onlooker_bees[i] = true;
591 }
592 for i in employed_count + onlooker_count..self.config.swarm_size {
593 scout_bees[i] = true;
594 }
595
596 let trial_counters = Array1::zeros(self.config.swarm_size);
597 let nectar_amounts = Array1::from_shape_fn(self.config.swarm_size, |_| {
598 rand::rng().random_range(0.0..1.0)
599 });
600
601 swarm.algorithm_state = AlgorithmSpecificState::ArtificialBee {
602 employed_bees,
603 onlooker_bees,
604 scout_bees,
605 trial_counters,
606 nectar_amounts,
607 };
608
609 Ok(())
610 }
611
612 fn initialize_firefly_state(
613 &self,
614 swarm: &mut SwarmState,
615 _bounds: &[(f64, f64)],
616 ) -> ScirsResult<()> {
617 let brightness_matrix =
618 Array2::from_shape_fn((self.config.swarm_size, self.config.swarm_size), |_| {
619 rand::rng().random_range(0.0..1.0)
620 });
621
622 let attraction_matrix =
623 Array2::from_shape_fn((self.config.swarm_size, self.config.swarm_size), |_| {
624 rand::rng().random_range(0.0..1.0)
625 });
626
627 let randomization_factors = Array1::from_shape_fn(self.config.swarm_size, |_| {
628 rand::rng().random_range(0.2..0.8)
629 });
630
631 swarm.algorithm_state = AlgorithmSpecificState::Firefly {
632 brightness_matrix,
633 attraction_matrix,
634 randomization_factors,
635 light_absorption: 1.0,
636 };
637
638 Ok(())
639 }
640
641 fn initialize_cuckoo_search_state(
642 &self,
643 swarm: &mut SwarmState,
644 bounds: &[(f64, f64)],
645 ) -> ScirsResult<()> {
646 let problem_dim = bounds.len();
647 let levy_flights = Array2::from_shape_fn((self.config.swarm_size, problem_dim), |_| {
648 let beta = 1.5;
650 let sigma = (tgamma(1.0 + beta) * (2.0 * std::f64::consts::PI).sin() * beta
651 / 2.0
652 / (tgamma((1.0 + beta) / 2.0) * beta * 2.0_f64.powf((beta - 1.0) / 2.0)))
653 .powf(1.0 / beta);
654
655 let u = rand::rng().random_range(0.0..1.0) * sigma;
656 let v: f64 = rand::rng().random_range(0.0..1.0);
657 u / v.abs().powf(1.0 / beta)
658 });
659
660 let step_sizes = Array1::from_shape_fn(self.config.swarm_size, |_| {
661 rand::rng().random_range(0.01..0.11)
662 });
663
664 swarm.algorithm_state = AlgorithmSpecificState::CuckooSearch {
665 levy_flights,
666 discovery_probability: 0.25,
667 step_sizes,
668 };
669
670 Ok(())
671 }
672
673 fn update_all_swarms_parallel<F>(&mut self, objective: &F, iteration: usize) -> ScirsResult<()>
674 where
675 F: GpuFunction + Send + Sync,
676 {
677 self.evaluate_all_swarms_gpu(objective)?;
679
680 let swarm_updates: Vec<(usize, AlgorithmSpecificState)> = self
683 .swarm_states
684 .iter()
685 .enumerate()
686 .map(|(idx, swarm)| (idx, swarm.algorithm_state.clone()))
687 .collect();
688
689 for (swarm_idx, algorithm_state) in swarm_updates {
691 match algorithm_state {
692 AlgorithmSpecificState::ParticleSwarm { .. } => {
693 if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
694 Self::update_particle_swarm_gpu_static(
695 swarm,
696 swarm_idx,
697 iteration,
698 &self.config,
699 )?;
700 }
701 }
702 AlgorithmSpecificState::AntColony { .. } => {
703 if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
704 Self::update_ant_colony_gpu_static(
705 swarm,
706 swarm_idx,
707 iteration,
708 &self.config,
709 )?;
710 }
711 }
712 AlgorithmSpecificState::ArtificialBee { .. } => {
713 if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
714 Self::update_bee_colony_gpu_static(
715 swarm,
716 swarm_idx,
717 iteration,
718 &self.config,
719 )?;
720 }
721 }
722 AlgorithmSpecificState::Firefly { .. } => {
723 if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
724 Self::update_firefly_gpu_static(swarm, swarm_idx, iteration, &self.config)?;
725 }
726 }
727 AlgorithmSpecificState::CuckooSearch { .. } => {
728 if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
729 Self::update_cuckoo_search_gpu_static(
730 swarm,
731 swarm_idx,
732 iteration,
733 &self.config,
734 )?;
735 }
736 }
737 _ => {
738 if let Some(swarm) = self.swarm_states.get_mut(swarm_idx) {
740 Self::update_particle_swarm_gpu_static(
741 swarm,
742 swarm_idx,
743 iteration,
744 &self.config,
745 )?;
746 }
747 }
748 }
749 }
750
751 Ok(())
752 }
753
754 fn evaluate_all_swarms_gpu<F>(&mut self, objective: &F) -> ScirsResult<()>
755 where
756 F: GpuFunction,
757 {
758 let total_agents = self.config.swarm_size * self.config.num_swarms;
760 let problem_dim = self.swarm_states[0].positions.ncols();
761
762 let mut all_positions = Array2::zeros((total_agents, problem_dim));
763
764 for (swarm_idx, swarm) in self.swarm_states.iter().enumerate() {
766 let start_idx = swarm_idx * self.config.swarm_size;
767 let _end_idx = start_idx + self.config.swarm_size;
768
769 for i in 0..self.config.swarm_size {
770 for j in 0..problem_dim {
771 all_positions[[start_idx + i, j]] = swarm.positions[[i, j]];
772 }
773 }
774 }
775
776 let all_fitness = self
778 .gpu_context
779 .evaluate_function_batch(objective, &all_positions)?;
780
781 for (swarm_idx, swarm) in self.swarm_states.iter_mut().enumerate() {
783 let start_idx = swarm_idx * self.config.swarm_size;
784
785 for i in 0..self.config.swarm_size {
786 swarm.current_fitness[i] = all_fitness[start_idx + i];
787
788 if swarm.current_fitness[i] < swarm.personal_best_fitness[i] {
790 swarm.personal_best_fitness[i] = swarm.current_fitness[i];
791 for j in 0..problem_dim {
792 swarm.personal_bests[[i, j]] = swarm.positions[[i, j]];
793 }
794 }
795
796 if swarm.current_fitness[i] < swarm.local_best_fitness {
798 swarm.local_best_fitness = swarm.current_fitness[i];
799 for j in 0..problem_dim {
800 swarm.local_best[j] = swarm.positions[[i, j]];
801 }
802 }
803 }
804 }
805
806 Ok(())
807 }
808
809 fn update_particle_swarm_gpu(
810 &mut self,
811 swarm: &mut SwarmState,
812 _swarm_idx: usize,
813 iteration: usize,
814 ) -> ScirsResult<()> {
815 if let AlgorithmSpecificState::ParticleSwarm {
817 ref mut inertia_weights,
818 ref acceleration_coefficients,
819 ref neighborhood_topology,
820 } = swarm.algorithm_state
821 {
822 let w_max = 0.9;
824 let w_min = 0.4;
825 let max_iter = self.config.max_nit as f64;
826 let current_iter = iteration as f64;
827 let base_inertia = w_max - (w_max - w_min) * current_iter / max_iter;
828
829 for i in 0..self.config.swarm_size {
831 if swarm.current_fitness[i] < swarm.personal_best_fitness[i] {
832 inertia_weights[i] = base_inertia * 1.1; } else {
834 inertia_weights[i] = base_inertia * 0.9; }
836 inertia_weights[i] = inertia_weights[i].max(w_min).min(w_max);
837 }
838
839 let problem_dim = swarm.positions.ncols();
841
842 for i in 0..self.config.swarm_size {
843 for j in 0..problem_dim {
844 let r1 = rand::rng().random_range(0.0..1.0);
845 let r2 = rand::rng().random_range(0.0..1.0);
846
847 let cognitive_component = acceleration_coefficients[[i, 0]]
848 * r1
849 * (swarm.personal_bests[[i, j]] - swarm.positions[[i, j]]);
850
851 let social_component = acceleration_coefficients[[i, 1]]
852 * r2
853 * (self.global_best.position[j] - swarm.positions[[i, j]]);
854
855 swarm.velocities[[i, j]] = inertia_weights[i] * swarm.velocities[[i, j]]
857 + cognitive_component
858 + social_component;
859
860 let v_max = 0.2 * (swarm.positions[[i, j]].abs() + 1.0);
862 swarm.velocities[[i, j]] = swarm.velocities[[i, j]].max(-v_max).min(v_max);
863
864 swarm.positions[[i, j]] += swarm.velocities[[i, j]];
866 }
867 }
868 }
869
870 Ok(())
871 }
872
873 fn update_ant_colony_gpu(
874 &mut self,
875 swarm: &mut SwarmState,
876 _swarm_idx: usize,
877 _iteration: usize,
878 ) -> ScirsResult<()> {
879 if let AlgorithmSpecificState::AntColony {
880 ref mut pheromone_matrix,
881 ref mut pheromone_update_matrix,
882 evaporation_rate,
883 pheromone_deposit,
884 } = swarm.algorithm_state
885 {
886 let problem_dim = swarm.positions.ncols();
887
888 for i in 0..problem_dim {
890 for j in 0..problem_dim {
891 pheromone_matrix[[i, j]] *= 1.0 - evaporation_rate;
892 pheromone_matrix[[i, j]] = pheromone_matrix[[i, j]].max(0.01);
893 }
895 }
896
897 for ant_idx in 0..self.config.swarm_size {
899 for dim in 0..problem_dim {
901 let mut best_move = 0.0;
902 let mut best_prob = 0.0;
903
904 for next_dim in 0..problem_dim {
906 if next_dim != dim {
907 let pheromone = pheromone_matrix[[dim, next_dim]];
908 let heuristic = 1.0
909 / (1.0
910 + (swarm.positions[[ant_idx, next_dim]]
911 - swarm.local_best[next_dim])
912 .abs());
913 let probability = pheromone.powf(1.0) * heuristic.powf(2.0);
914
915 if probability > best_prob {
916 best_prob = probability;
917 best_move = (swarm.local_best[next_dim]
918 - swarm.positions[[ant_idx, dim]])
919 * 0.1;
920 }
921 }
922 }
923
924 swarm.positions[[ant_idx, dim]] +=
926 best_move + rand::rng().random_range(-0.005..0.005);
927 }
928
929 if swarm.current_fitness[ant_idx] < f64::INFINITY {
931 let deposit_amount = pheromone_deposit / (1.0 + swarm.current_fitness[ant_idx]);
932 for i in 0..problem_dim {
933 for j in 0..problem_dim {
934 if i != j {
935 pheromone_update_matrix[[i, j]] += deposit_amount;
936 }
937 }
938 }
939 }
940 }
941
942 for i in 0..problem_dim {
944 for j in 0..problem_dim {
945 pheromone_matrix[[i, j]] += pheromone_update_matrix[[i, j]];
946 pheromone_update_matrix[[i, j]] = 0.0; }
948 }
949 }
950
951 Ok(())
952 }
953
954 fn update_bee_colony_gpu(
955 &mut self,
956 swarm: &mut SwarmState,
957 swarm_idx: usize,
958 iteration: usize,
959 ) -> ScirsResult<()> {
960 if let AlgorithmSpecificState::ArtificialBee {
961 ref employed_bees,
962 ref onlooker_bees,
963 ref scout_bees,
964 ref mut trial_counters,
965 ref mut nectar_amounts,
966 } = swarm.algorithm_state
967 {
968 let problem_dim = swarm.positions.ncols();
969 let limit = 100; for i in 0..self.config.swarm_size {
973 if employed_bees[i] {
974 let partner = loop {
976 let p = rand::rng().random_range(0..self.config.swarm_size);
977 if p != i {
978 break p;
979 }
980 };
981
982 let dimension = rand::rng().random_range(0..problem_dim);
983 let phi = rand::rng().random_range(-1.0..1.0);
984
985 let mut new_position = swarm.positions.row(i).to_owned();
986 new_position[dimension] = swarm.positions[[i, dimension]]
987 + phi
988 * (swarm.positions[[i, dimension]]
989 - swarm.positions[[partner, dimension]]);
990
991 let new_fitness =
993 swarm.current_fitness[i] + rand::rng().random_range(-0.05..0.05);
994
995 if new_fitness < swarm.current_fitness[i] {
997 for j in 0..problem_dim {
998 swarm.positions[[i, j]] = new_position[j];
999 }
1000 swarm.current_fitness[i] = new_fitness;
1001 trial_counters[i] = 0;
1002 nectar_amounts[i] = 1.0 / (1.0 + new_fitness.abs());
1003 } else {
1004 trial_counters[i] += 1;
1005 }
1006 }
1007 }
1008
1009 let total_nectar: f64 = nectar_amounts.sum();
1011 for i in 0..self.config.swarm_size {
1012 if onlooker_bees[i] && total_nectar > 0.0 {
1013 let mut cumulative = 0.0;
1015 let random_val = rand::rng().random_range(0.0..1.0);
1016
1017 for j in 0..self.config.swarm_size {
1018 cumulative += nectar_amounts[j] / total_nectar;
1019 if random_val <= cumulative {
1020 let dimension = rand::rng().random_range(0..problem_dim);
1022 let phi = rand::rng().random_range(-1.0..1.0);
1023
1024 swarm.positions[[i, dimension]] = swarm.positions[[j, dimension]]
1025 + phi
1026 * (swarm.positions[[j, dimension]]
1027 - swarm.local_best[dimension]);
1028 break;
1029 }
1030 }
1031 }
1032 }
1033
1034 for i in 0..self.config.swarm_size {
1036 if trial_counters[i] > limit {
1037 for j in 0..problem_dim {
1039 swarm.positions[[i, j]] = rand::rng().random_range(-1.0..1.0);
1040 }
1041 trial_counters[i] = 0;
1042 nectar_amounts[i] = rand::rng().random_range(0.0..1.0);
1043 }
1044 }
1045 }
1046
1047 Ok(())
1048 }
1049
1050 fn update_firefly_gpu(
1051 &mut self,
1052 swarm: &mut SwarmState,
1053 _swarm_idx: usize,
1054 _iteration: usize,
1055 ) -> ScirsResult<()> {
1056 if let AlgorithmSpecificState::Firefly {
1057 ref mut brightness_matrix,
1058 ref mut attraction_matrix,
1059 ref randomization_factors,
1060 light_absorption,
1061 } = swarm.algorithm_state
1062 {
1063 let problem_dim = swarm.positions.ncols();
1064 let beta0 = 1.0; let alpha = 0.2; for i in 0..self.config.swarm_size {
1069 for j in 0..self.config.swarm_size {
1070 brightness_matrix[[i, j]] = 1.0 / (1.0 + swarm.current_fitness[j].abs());
1071 }
1072 }
1073
1074 for i in 0..self.config.swarm_size {
1076 for j in 0..self.config.swarm_size {
1077 if i != j && brightness_matrix[[i, j]] > brightness_matrix[[i, i]] {
1078 let mut distance_sq = 0.0;
1080 for k in 0..problem_dim {
1081 let diff = swarm.positions[[i, k]] - swarm.positions[[j, k]];
1082 distance_sq += diff * diff;
1083 }
1084
1085 let _distance = distance_sq.sqrt();
1087 let attraction = beta0 * (-light_absorption * distance_sq).exp();
1088 attraction_matrix[[i, j]] = attraction;
1089
1090 for k in 0..problem_dim {
1092 let randomization = alpha
1093 * rand::rng().random_range(-0.5..0.5)
1094 * randomization_factors[i];
1095 swarm.positions[[i, k]] += attraction
1096 * (swarm.positions[[j, k]] - swarm.positions[[i, k]])
1097 + randomization;
1098 }
1099 }
1100 }
1101
1102 let mut moved = false;
1104 for j in 0..self.config.swarm_size {
1105 if brightness_matrix[[i, j]] > brightness_matrix[[i, i]] {
1106 moved = true;
1107 break;
1108 }
1109 }
1110
1111 if !moved {
1112 for k in 0..problem_dim {
1113 let randomization =
1114 alpha * rand::rng().random_range(-0.5..0.5) * randomization_factors[i];
1115 swarm.positions[[i, k]] += randomization;
1116 }
1117 }
1118 }
1119 }
1120
1121 Ok(())
1122 }
1123
1124 fn update_cuckoo_search_gpu(
1125 &mut self,
1126 swarm: &mut SwarmState,
1127 swarm_idx: usize,
1128 iteration: usize,
1129 ) -> ScirsResult<()> {
1130 if let AlgorithmSpecificState::CuckooSearch {
1131 ref mut levy_flights,
1132 discovery_probability,
1133 ref step_sizes,
1134 } = swarm.algorithm_state
1135 {
1136 let problem_dim = swarm.positions.ncols();
1137
1138 for i in 0..self.config.swarm_size {
1140 for j in 0..problem_dim {
1142 let levy_step = self.generate_levy_flight();
1143 levy_flights[[i, j]] = levy_step * step_sizes[i];
1144
1145 let new_pos = swarm.positions[[i, j]]
1147 + levy_flights[[i, j]] * (swarm.positions[[i, j]] - swarm.local_best[j]);
1148
1149 swarm.positions[[i, j]] = new_pos;
1150 }
1151
1152 let random_nest = rand::rng().random_range(0..self.config.swarm_size);
1154 if rand::rng().random_range(0.0..1.0) < 0.5
1155 && swarm.current_fitness[i] < swarm.current_fitness[random_nest]
1156 {
1157 for j in 0..problem_dim {
1159 swarm.positions[[random_nest, j]] = swarm.positions[[i, j]];
1160 }
1161 }
1162 }
1163
1164 for i in 0..self.config.swarm_size {
1166 if rand::rng().random_range(0.0..1.0) < discovery_probability {
1167 for j in 0..problem_dim {
1169 swarm.positions[[i, j]] = rand::rng().random_range(-1.0..1.0);
1170 }
1171 }
1172 }
1173 }
1174
1175 Ok(())
1176 }
1177
1178 fn generate_levy_flight(&self) -> f64 {
1179 let beta = 1.5;
1180 let sigma = (tgamma(1.0 + beta) * (2.0 * std::f64::consts::PI * beta / 2.0).sin()
1181 / (tgamma((1.0 + beta) / 2.0) * beta * 2.0_f64.powf((beta - 1.0) / 2.0)))
1182 .powf(1.0 / beta);
1183
1184 let u = rand::rng().random_range(0.0..1.0) * sigma;
1185 let v: f64 = rand::rng().random_range(0.0..1.0);
1186
1187 u / v.abs().powf(1.0 / beta)
1188 }
1189
1190 fn update_global_best(&mut self, iteration: usize) -> ScirsResult<()> {
1191 let mut improved = false;
1192
1193 for (swarm_idx, swarm) in self.swarm_states.iter().enumerate() {
1194 if swarm.local_best_fitness < self.global_best.fitness {
1195 self.global_best.fitness = swarm.local_best_fitness;
1196 self.global_best.position = swarm.local_best.clone();
1197 self.global_best.found_by_swarm = swarm_idx;
1198 self.global_best.iteration_found = iteration;
1199 improved = true;
1200 }
1201 }
1202
1203 if improved {
1204 self.global_best.stagnation_counter = 0;
1205 } else {
1206 self.global_best.stagnation_counter += 1;
1207 }
1208
1209 self.global_best
1210 .improvement_history
1211 .push(self.global_best.fitness);
1212
1213 Ok(())
1214 }
1215
1216 fn perform_swarm_migration(&mut self) -> ScirsResult<()> {
1217 for pattern in &self.topology_manager.migration_patterns.clone() {
1219 let source_swarm = pattern.source_swarm;
1220 let target_swarm = pattern.target_swarm;
1221
1222 if source_swarm < self.swarm_states.len() && target_swarm < self.swarm_states.len() {
1223 let migration_count =
1224 (self.config.swarm_size as f64 * pattern.migration_rate) as usize;
1225
1226 let migrants: Vec<usize> = match pattern.selection_strategy {
1228 SelectionStrategy::Best => {
1229 let mut indices: Vec<usize> = (0..self.config.swarm_size).collect();
1231 indices.sort_by(|&a, &b| {
1232 self.swarm_states[source_swarm].current_fitness[a]
1233 .partial_cmp(&self.swarm_states[source_swarm].current_fitness[b])
1234 .unwrap()
1235 });
1236 indices.into_iter().take(migration_count).collect()
1237 }
1238 SelectionStrategy::Random => {
1239 (0..migration_count)
1241 .map(|_| rand::rng().random_range(0..self.config.swarm_size))
1242 .collect()
1243 }
1244 SelectionStrategy::Diverse => {
1245 (0..migration_count)
1247 .map(|i| i * self.config.swarm_size / migration_count)
1248 .collect()
1249 }
1250 SelectionStrategy::Elite => {
1251 let elite_count = (self.config.swarm_size as f64 * 0.1) as usize;
1253 let mut indices: Vec<usize> = (0..self.config.swarm_size).collect();
1254 indices.sort_by(|&a, &b| {
1255 self.swarm_states[source_swarm].current_fitness[a]
1256 .partial_cmp(&self.swarm_states[source_swarm].current_fitness[b])
1257 .unwrap()
1258 });
1259 indices
1260 .into_iter()
1261 .take(elite_count.min(migration_count))
1262 .collect()
1263 }
1264 };
1265
1266 let problem_dim = self.swarm_states[source_swarm].positions.ncols();
1268 for (target_idx, &source_idx) in migrants.iter().enumerate() {
1269 if target_idx < self.config.swarm_size {
1270 for j in 0..problem_dim {
1271 self.swarm_states[target_swarm].positions[[target_idx, j]] =
1272 self.swarm_states[source_swarm].positions[[source_idx, j]];
1273 }
1274 }
1275 }
1276 }
1277 }
1278
1279 Ok(())
1280 }
1281
1282 fn adapt_topology(&mut self) -> ScirsResult<()> {
1283 let mut avg_performance = 0.0;
1285 let mut min_diversity = f64::INFINITY;
1286
1287 for swarm in &self.swarm_states {
1288 avg_performance += swarm.local_best_fitness;
1289 min_diversity = min_diversity.min(swarm.diversity);
1290 }
1291 avg_performance /= self.swarm_states.len() as f64;
1292
1293 if min_diversity < self.topology_manager.adaptation_rules.diversity_threshold {
1295 self.topology_manager.current_topology = match self.topology_manager.current_topology {
1297 TopologyType::Ring => TopologyType::Star,
1298 TopologyType::Star => TopologyType::Random,
1299 TopologyType::Random => TopologyType::SmallWorld,
1300 TopologyType::SmallWorld => TopologyType::ScaleFree,
1301 TopologyType::ScaleFree => TopologyType::Adaptive,
1302 TopologyType::Adaptive => TopologyType::Ring, };
1304 }
1305
1306 self.topology_manager.migration_patterns.clear();
1308
1309 match self.topology_manager.current_topology {
1310 TopologyType::Ring => {
1311 for i in 0..self.config.num_swarms {
1312 let next = (i + 1) % self.config.num_swarms;
1313 self.topology_manager
1314 .migration_patterns
1315 .push(MigrationPattern {
1316 source_swarm: i,
1317 target_swarm: next,
1318 migration_rate: 0.1,
1319 selection_strategy: SelectionStrategy::Best,
1320 });
1321 }
1322 }
1323 TopologyType::Star => {
1324 for i in 1..self.config.num_swarms {
1326 self.topology_manager
1327 .migration_patterns
1328 .push(MigrationPattern {
1329 source_swarm: i,
1330 target_swarm: 0,
1331 migration_rate: 0.15,
1332 selection_strategy: SelectionStrategy::Elite,
1333 });
1334 self.topology_manager
1335 .migration_patterns
1336 .push(MigrationPattern {
1337 source_swarm: 0,
1338 target_swarm: i,
1339 migration_rate: 0.05,
1340 selection_strategy: SelectionStrategy::Best,
1341 });
1342 }
1343 }
1344 TopologyType::Random => {
1345 for _ in 0..self.config.num_swarms {
1347 let source = rand::rng().random_range(0..self.config.num_swarms);
1348 let target = rand::rng().random_range(0..self.config.num_swarms);
1349 if source != target {
1350 self.topology_manager
1351 .migration_patterns
1352 .push(MigrationPattern {
1353 source_swarm: source,
1354 target_swarm: target,
1355 migration_rate: 0.08,
1356 selection_strategy: SelectionStrategy::Random,
1357 });
1358 }
1359 }
1360 }
1361 _ => {
1362 for i in 0..self.config.num_swarms {
1364 let next = (i + 1) % self.config.num_swarms;
1365 self.topology_manager
1366 .migration_patterns
1367 .push(MigrationPattern {
1368 source_swarm: i,
1369 target_swarm: next,
1370 migration_rate: 0.1,
1371 selection_strategy: SelectionStrategy::Diverse,
1372 });
1373 }
1374 }
1375 }
1376
1377 Ok(())
1378 }
1379
1380 fn maintain_swarm_diversity(&mut self) -> ScirsResult<()> {
1381 let diversities: Result<Vec<_>, _> = self
1384 .swarm_states
1385 .iter()
1386 .map(|swarm| self.compute_swarm_diversity(swarm))
1387 .collect();
1388 let diversities = diversities?;
1389
1390 for (swarm, diversity) in self.swarm_states.iter_mut().zip(diversities.iter()) {
1392 swarm.diversity = *diversity;
1393
1394 if *diversity < self.config.diversity_threshold {
1396 let reinit_count = (self.config.swarm_size as f64 * 0.1) as usize;
1397 for i in 0..reinit_count {
1398 let idx = rand::rng().random_range(0..self.config.swarm_size);
1399 for j in 0..swarm.positions.ncols() {
1401 swarm.positions[[idx, j]] = rand::rng().random_range(-1.0..1.0);
1402 }
1403 }
1404 }
1405 }
1406
1407 Ok(())
1408 }
1409
1410 fn compute_swarm_diversity(&self, swarm: &SwarmState) -> ScirsResult<f64> {
1411 let n_agents = swarm.positions.nrows();
1412 let n_dims = swarm.positions.ncols();
1413
1414 if n_agents < 2 {
1415 return Ok(0.0);
1416 }
1417
1418 let mut total_distance = 0.0;
1419 let mut count = 0;
1420
1421 for i in 0..n_agents {
1422 for j in i + 1..n_agents {
1423 let mut distance = 0.0;
1424 for k in 0..n_dims {
1425 let diff = swarm.positions[[i, k]] - swarm.positions[[j, k]];
1426 distance += diff * diff;
1427 }
1428 total_distance += distance.sqrt();
1429 count += 1;
1430 }
1431 }
1432
1433 Ok(if count > 0 {
1434 total_distance / count as f64
1435 } else {
1436 0.0
1437 })
1438 }
1439
1440 fn update_performance_metrics(&mut self, iteration: usize) -> ScirsResult<()> {
1441 for (swarm_idx, swarm) in self.swarm_states.iter().enumerate() {
1443 self.performance_monitor.evaluations_per_swarm[swarm_idx] += self.config.swarm_size;
1444
1445 if iteration > 0 {
1447 let prev_fitness = self.performance_monitor.diversity_history[swarm_idx]
1448 .last()
1449 .copied()
1450 .unwrap_or(swarm.local_best_fitness);
1451 let improvement = prev_fitness - swarm.local_best_fitness;
1452 self.performance_monitor.convergence_rates[swarm_idx] = improvement;
1453 }
1454
1455 self.performance_monitor.diversity_history[swarm_idx].push(swarm.diversity);
1457 }
1458
1459 Ok(())
1460 }
1461
1462 fn check_convergence(&self) -> ScirsResult<bool> {
1463 let stagnation_limit = 100;
1465 let fitness_threshold = 1e-10;
1466
1467 if self.global_best.stagnation_counter > stagnation_limit {
1468 return Ok(true);
1469 }
1470
1471 if self.global_best.fitness < fitness_threshold {
1472 return Ok(true);
1473 }
1474
1475 let mut all_converged = true;
1477 let convergence_tolerance = 1e-6;
1478
1479 for swarm in &self.swarm_states {
1480 if (swarm.local_best_fitness - self.global_best.fitness).abs() > convergence_tolerance {
1481 all_converged = false;
1482 break;
1483 }
1484 }
1485
1486 Ok(all_converged)
1487 }
1488
1489 pub fn get_swarm_statistics(&self) -> SwarmOptimizationStats {
1491 SwarmOptimizationStats {
1492 total_function_evaluations: self.performance_monitor.evaluations_per_swarm.iter().sum(),
1493 global_best_fitness: self.global_best.fitness,
1494 convergence_iteration: self.global_best.iteration_found,
1495 best_swarm_id: self.global_best.found_by_swarm,
1496 average_swarm_diversity: self.swarm_states.iter().map(|s| s.diversity).sum::<f64>()
1497 / self.swarm_states.len() as f64,
1498 gpu_utilization: self.performance_monitor.gpu_utilization.clone(),
1499 algorithm_performance: self.performance_monitor.algorithm_performance.clone(),
1500 migration_statistics: MigrationStatistics {
1501 total_migrations: self.topology_manager.migration_patterns.len(),
1502 migration_frequency: self.config.migration_frequency,
1503 successful_migrations: 0, },
1505 }
1506 }
1507
1508 fn update_particle_swarm_gpu_static(
1510 _swarm: &mut SwarmState,
1511 _swarm_idx: usize,
1512 _iteration: usize,
1513 config: &AdvancedSwarmConfig,
1514 ) -> ScirsResult<()> {
1515 Ok(())
1517 }
1518
1519 fn update_ant_colony_gpu_static(
1520 _swarm: &mut SwarmState,
1521 _swarm_idx: usize,
1522 _iteration: usize,
1523 config: &AdvancedSwarmConfig,
1524 ) -> ScirsResult<()> {
1525 Ok(())
1527 }
1528
1529 fn update_bee_colony_gpu_static(
1530 _swarm: &mut SwarmState,
1531 _swarm_idx: usize,
1532 _iteration: usize,
1533 config: &AdvancedSwarmConfig,
1534 ) -> ScirsResult<()> {
1535 Ok(())
1537 }
1538
1539 fn update_firefly_gpu_static(
1540 _swarm: &mut SwarmState,
1541 _swarm_idx: usize,
1542 _iteration: usize,
1543 config: &AdvancedSwarmConfig,
1544 ) -> ScirsResult<()> {
1545 Ok(())
1547 }
1548
1549 fn update_cuckoo_search_gpu_static(
1550 _swarm: &mut SwarmState,
1551 _swarm_idx: usize,
1552 _iteration: usize,
1553 config: &AdvancedSwarmConfig,
1554 ) -> ScirsResult<()> {
1555 Ok(())
1557 }
1558
1559 fn initialize_particle_swarm_state_static(
1561 swarm: &mut SwarmState,
1562 _bounds: &[(f64, f64)],
1563 swarm_size: usize,
1564 ) -> ScirsResult<()> {
1565 swarm.algorithm_state = AlgorithmSpecificState::ParticleSwarm {
1566 inertia_weights: Array1::from_elem(swarm_size, 0.7),
1567 acceleration_coefficients: Array2::from_elem((swarm_size, 2), 2.0),
1568 neighborhood_topology: Array2::from_elem((swarm_size, swarm_size), false),
1569 };
1570 Ok(())
1571 }
1572
1573 fn initialize_ant_colony_state_static(
1574 swarm: &mut SwarmState,
1575 _bounds: &[(f64, f64)],
1576 swarm_size: usize,
1577 ) -> ScirsResult<()> {
1578 swarm.algorithm_state = AlgorithmSpecificState::AntColony {
1579 pheromone_matrix: Array2::zeros((swarm_size, swarm_size)),
1580 pheromone_update_matrix: Array2::zeros((swarm_size, swarm_size)),
1581 evaporation_rate: 0.1,
1582 pheromone_deposit: 1.0,
1583 };
1584 Ok(())
1585 }
1586
1587 fn initialize_bee_colony_state_static(
1588 swarm: &mut SwarmState,
1589 _bounds: &[(f64, f64)],
1590 swarm_size: usize,
1591 ) -> ScirsResult<()> {
1592 swarm.algorithm_state = AlgorithmSpecificState::ArtificialBee {
1593 employed_bees: Array1::from_elem(swarm_size / 2, true),
1594 onlooker_bees: Array1::from_elem(swarm_size / 2, true),
1595 scout_bees: Array1::from_elem(swarm_size - swarm_size / 2 - swarm_size / 2, false),
1596 trial_counters: Array1::zeros(swarm_size),
1597 nectar_amounts: Array1::zeros(swarm_size),
1598 };
1599 Ok(())
1600 }
1601
1602 fn initialize_firefly_state_static(
1603 swarm: &mut SwarmState,
1604 _bounds: &[(f64, f64)],
1605 swarm_size: usize,
1606 ) -> ScirsResult<()> {
1607 swarm.algorithm_state = AlgorithmSpecificState::Firefly {
1608 brightness_matrix: Array2::from_elem((swarm_size, swarm_size), 1.0),
1609 attraction_matrix: Array2::from_elem((swarm_size, swarm_size), 1.0),
1610 randomization_factors: Array1::from_elem(swarm_size, 0.2),
1611 light_absorption: 1.0,
1612 };
1613 Ok(())
1614 }
1615
1616 fn initialize_cuckoo_search_state_static(
1617 swarm: &mut SwarmState,
1618 _bounds: &[(f64, f64)],
1619 swarm_size: usize,
1620 ) -> ScirsResult<()> {
1621 swarm.algorithm_state = AlgorithmSpecificState::CuckooSearch {
1622 levy_flights: Array2::from_elem((swarm_size, 1), 1.0),
1623 discovery_probability: 0.25,
1624 step_sizes: Array1::from_elem(swarm_size, 0.01),
1625 };
1626 Ok(())
1627 }
1628}
1629
1630impl SwarmState {
1631 fn new(config: &AdvancedSwarmConfig) -> ScirsResult<Self> {
1632 let dummy_dim = 10; Ok(Self {
1636 positions: Array2::zeros((config.swarm_size, dummy_dim)),
1637 velocities: Array2::zeros((config.swarm_size, dummy_dim)),
1638 personal_bests: Array2::zeros((config.swarm_size, dummy_dim)),
1639 personal_best_fitness: Array1::from_elem(config.swarm_size, f64::INFINITY),
1640 current_fitness: Array1::from_elem(config.swarm_size, f64::INFINITY),
1641 local_best: Array1::zeros(dummy_dim),
1642 local_best_fitness: f64::INFINITY,
1643 agent_parameters: Array2::zeros((config.swarm_size, 4)), diversity: 1.0,
1645 algorithm_state: AlgorithmSpecificState::ParticleSwarm {
1646 inertia_weights: Array1::zeros(config.swarm_size),
1647 acceleration_coefficients: Array2::zeros((config.swarm_size, 2)),
1648 neighborhood_topology: Array2::from_elem(
1649 (config.swarm_size, config.swarm_size),
1650 false,
1651 ),
1652 },
1653 })
1654 }
1655}
1656
1657impl SwarmTopologyManager {
1658 fn new(num_swarms: usize) -> Self {
1659 let communication_matrix = Array2::from_elem((num_swarms, num_swarms), 0.1);
1660 let migration_patterns = Vec::new(); let adaptation_rules = TopologyAdaptationRules {
1662 performance_threshold: 0.9,
1663 diversity_threshold: 0.1,
1664 stagnation_threshold: 50,
1665 adaptation_frequency: 100,
1666 };
1667
1668 Self {
1669 communication_matrix,
1670 migration_patterns,
1671 adaptation_rules,
1672 current_topology: TopologyType::Ring,
1673 }
1674 }
1675}
1676
1677impl SwarmPerformanceMonitor {
1678 fn new(num_swarms: usize) -> Self {
1679 Self {
1680 evaluations_per_swarm: vec![0; num_swarms],
1681 convergence_rates: vec![0.0; num_swarms],
1682 diversity_history: vec![Vec::new(); num_swarms],
1683 gpu_utilization: GPUUtilizationMetrics {
1684 compute_utilization: 0.0,
1685 memory_utilization: 0.0,
1686 kernel_execution_times: HashMap::new(),
1687 memory_bandwidth_usage: 0.0,
1688 tensor_core_utilization: 0.0,
1689 },
1690 algorithm_performance: HashMap::new(),
1691 }
1692 }
1693}
1694
1695impl SwarmKernelCache {
1696 fn new(context: Arc<super::GpuContext>) -> ScirsResult<Self> {
1697 Ok(Self {
1698 pso_kernel: ParticleSwarmKernel::new(Arc::clone(&context))?,
1699 aco_kernel: AntColonyKernel,
1700 abc_kernel: ArtificialBeeKernel,
1701 firefly_kernel: FireflyKernel,
1702 cuckoo_kernel: CuckooSearchKernel,
1703 bacterial_kernel: BacterialForagingKernel,
1704 grey_wolf_kernel: GreyWolfKernel,
1705 whale_kernel: WhaleOptimizationKernel,
1706 migration_kernel: MigrationKernel,
1707 diversity_kernel: DiversityComputationKernel,
1708 })
1709 }
1710}
1711
1712#[derive(Debug, Clone)]
1714pub struct SwarmOptimizationStats {
1715 pub total_function_evaluations: usize,
1716 pub global_best_fitness: f64,
1717 pub convergence_iteration: usize,
1718 pub best_swarm_id: usize,
1719 pub average_swarm_diversity: f64,
1720 pub gpu_utilization: GPUUtilizationMetrics,
1721 pub algorithm_performance: HashMap<SwarmAlgorithm, AlgorithmPerformance>,
1722 pub migration_statistics: MigrationStatistics,
1723}
1724
1725#[derive(Debug, Clone)]
1726pub struct MigrationStatistics {
1727 pub total_migrations: usize,
1728 pub migration_frequency: usize,
1729 pub successful_migrations: usize,
1730}
1731
1732#[allow(dead_code)]
1734pub fn advanced_parallel_swarm_optimize<F>(
1735 objective: F,
1736 bounds: &[(f64, f64)],
1737 config: Option<AdvancedSwarmConfig>,
1738) -> ScirsResult<OptimizeResults<f64>>
1739where
1740 F: GpuFunction + Send + Sync,
1741{
1742 let config = config.unwrap_or_default();
1743 let mut optimizer = AdvancedParallelSwarmOptimizer::new(config)?;
1744 optimizer.optimize(&objective, bounds)
1745}
1746
1747#[allow(dead_code)]
1749fn tgamma(x: f64) -> f64 {
1750 if x < 0.5 {
1752 std::f64::consts::PI / ((std::f64::consts::PI * x).sin() * tgamma(1.0 - x))
1753 } else {
1754 let g = 7;
1755 let coeffs = [
1756 0.99999999999980993,
1757 676.5203681218851,
1758 -1259.1392167224028,
1759 771.32342877765313,
1760 -176.61502916214059,
1761 12.507343278686905,
1762 -0.13857109526572012,
1763 9.9843695780195716e-6,
1764 1.5056327351493116e-7,
1765 ];
1766
1767 let z = x - 1.0;
1768 let mut a = coeffs[0];
1769 for i in 1..g + 2 {
1770 a += coeffs[i] / (z + i as f64);
1771 }
1772
1773 let t = z + g as f64 + 0.5;
1774 (2.0 * std::f64::consts::PI).sqrt() * t.powf(z + 0.5) * (-t).exp() * a
1775 }
1776}
1777
1778#[cfg(test)]
1779mod tests {
1780 use super::*;
1781
1782 #[test]
1783 fn test_advanced_swarmconfig() {
1784 let config = AdvancedSwarmConfig::default();
1785 assert_eq!(config.swarm_size, 10000);
1786 assert_eq!(config.num_swarms, 8);
1787 assert_eq!(config.algorithm, SwarmAlgorithm::AdaptiveEnsemble);
1788 }
1789
1790 #[test]
1791 fn test_swarm_state_creation() {
1792 let config = AdvancedSwarmConfig::default();
1793 let swarm = SwarmState::new(&config).unwrap();
1794 assert_eq!(swarm.positions.nrows(), config.swarm_size);
1795 assert_eq!(swarm.velocities.nrows(), config.swarm_size);
1796 }
1797
1798 #[test]
1799 fn test_topology_manager() {
1800 let manager = SwarmTopologyManager::new(5);
1801 assert_eq!(manager.communication_matrix.nrows(), 5);
1802 assert_eq!(manager.communication_matrix.ncols(), 5);
1803 }
1804
1805 #[test]
1806 fn test_performance_monitor() {
1807 let monitor = SwarmPerformanceMonitor::new(3);
1808 assert_eq!(monitor.evaluations_per_swarm.len(), 3);
1809 assert_eq!(monitor.convergence_rates.len(), 3);
1810 assert_eq!(monitor.diversity_history.len(), 3);
1811 }
1812
1813 #[test]
1814 fn test_algorithm_specific_state() {
1815 let state = AlgorithmSpecificState::ParticleSwarm {
1816 inertia_weights: Array1::zeros(10),
1817 acceleration_coefficients: Array2::zeros((10, 2)),
1818 neighborhood_topology: Array2::from_elem((10, 10), false),
1819 };
1820 match state {
1821 AlgorithmSpecificState::ParticleSwarm { .. } => {
1822 }
1824 _ => panic!("Wrong state type"),
1825 }
1826 }
1827}
1828
1829#[derive(Clone)]
1831pub struct AccelerationConfig {
1832 pub strategy: AccelerationStrategy,
1833 pub gpuconfig: GpuOptimizationConfig,
1834}
1835
1836impl Default for AccelerationConfig {
1837 fn default() -> Self {
1838 Self {
1839 strategy: AccelerationStrategy::Auto,
1840 gpuconfig: GpuOptimizationConfig::default(),
1841 }
1842 }
1843}
1844
1845#[derive(Debug, Clone, Copy)]
1846pub enum AccelerationStrategy {
1847 Auto,
1848 GPU,
1849 CPU,
1850}
1851
1852pub struct AccelerationManager {
1853 config: AccelerationConfig,
1854}
1855
1856impl AccelerationManager {
1857 pub fn new(config: AccelerationConfig) -> Self {
1858 Self { config }
1859 }
1860
1861 pub fn default() -> Self {
1862 Self::new(AccelerationConfig::default())
1863 }
1864}
1865
1866#[derive(Debug, Clone)]
1867pub struct PerformanceStats {
1868 pub gpu_utilization: f64,
1869 pub memory_usage: f64,
1870 pub throughput: f64,
1871}
1872
1873impl Default for PerformanceStats {
1874 fn default() -> Self {
1875 Self {
1876 gpu_utilization: 0.0,
1877 memory_usage: 0.0,
1878 throughput: 0.0,
1879 }
1880 }
1881}
1882
1883impl PerformanceStats {
1884 pub fn generate_report(&self) -> String {
1885 format!(
1886 "GPU Utilization: {:.2}%\nMemory Usage: {:.2}%\nThroughput: {:.2} ops/s",
1887 self.gpu_utilization * 100.0,
1888 self.memory_usage * 100.0,
1889 self.throughput
1890 )
1891 }
1892}