Skip to main content

quantrs2_sim/automatic_parallelization/
autoparallelengine_analyze_circuit_group.rs

1//! # AutoParallelEngine - analyze_circuit_group Methods
2//!
3//! This module contains method implementations for `AutoParallelEngine`.
4//!
5//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
6
7use crate::distributed_simulator::{DistributedQuantumSimulator, DistributedSimulatorConfig};
8use quantrs2_circuit::builder::{Circuit, Simulator};
9use quantrs2_core::{
10    error::{QuantRS2Error, QuantRS2Result},
11    gate::GateOp,
12    qubit::QubitId,
13};
14use scirs2_core::Complex64;
15use std::time::{Duration, Instant};
16
17use super::types::{
18    DependencyGraph, HardwareStrategy, MLPredictedStrategy, ParallelTask, ParallelizationAnalysis,
19    ParallelizationStrategy, ResourceUtilization,
20};
21
22use super::autoparallelengine_type::AutoParallelEngine;
23
24impl AutoParallelEngine {
25    /// Analyze a circuit for parallelization opportunities
26    pub fn analyze_circuit<const N: usize>(
27        &self,
28        circuit: &Circuit<N>,
29    ) -> QuantRS2Result<ParallelizationAnalysis> {
30        let start_time = Instant::now();
31        if self.config.enable_analysis_caching {
32            let circuit_hash = Self::compute_circuit_hash(circuit);
33            if let Some(cached_analysis) = self
34                .analysis_cache
35                .read()
36                .expect("analysis cache read lock should not be poisoned")
37                .get(&circuit_hash)
38            {
39                return Ok(cached_analysis.clone());
40            }
41        }
42        let dependency_graph = self.build_dependency_graph(circuit)?;
43        let tasks = match self.config.strategy {
44            ParallelizationStrategy::DependencyAnalysis => {
45                self.dependency_based_parallelization(&dependency_graph)?
46            }
47            ParallelizationStrategy::LayerBased => {
48                self.layer_based_parallelization(&dependency_graph)?
49            }
50            ParallelizationStrategy::QubitPartitioning => {
51                self.qubit_partitioning_parallelization(circuit, &dependency_graph)?
52            }
53            ParallelizationStrategy::Hybrid => {
54                self.hybrid_parallelization(circuit, &dependency_graph)?
55            }
56            ParallelizationStrategy::MLGuided => {
57                self.ml_guided_parallelization(circuit, &dependency_graph)?
58            }
59            ParallelizationStrategy::HardwareAware => {
60                self.hardware_aware_parallelization(circuit, &dependency_graph)?
61            }
62        };
63        let analysis = self.calculate_parallelization_metrics(circuit, &dependency_graph, tasks)?;
64        if self.config.enable_analysis_caching {
65            let circuit_hash = Self::compute_circuit_hash(circuit);
66            self.analysis_cache
67                .write()
68                .expect("analysis cache write lock should not be poisoned")
69                .insert(circuit_hash, analysis.clone());
70        }
71        self.update_performance_stats(start_time.elapsed(), &analysis);
72        Ok(analysis)
73    }
74    /// Execute circuit with distributed parallelization
75    pub fn execute_distributed<const N: usize>(
76        &self,
77        circuit: &Circuit<N>,
78        distributed_sim: &mut DistributedQuantumSimulator,
79    ) -> QuantRS2Result<Vec<Complex64>> {
80        let analysis = self.analyze_circuit(circuit)?;
81        let distributed_tasks =
82            self.distribute_tasks_across_nodes(&analysis.tasks, distributed_sim)?;
83        let results = self.execute_distributed_tasks(&distributed_tasks, distributed_sim)?;
84        let final_result = Self::aggregate_distributed_results(results)?;
85        Ok(final_result)
86    }
87    /// ML-guided parallelization strategy
88    pub(super) fn ml_guided_parallelization<const N: usize>(
89        &self,
90        circuit: &Circuit<N>,
91        graph: &DependencyGraph,
92    ) -> QuantRS2Result<Vec<ParallelTask>> {
93        let features = self.extract_ml_features(circuit, graph);
94        let predicted_strategy = Self::predict_parallelization_strategy(&features);
95        let task_groups = match predicted_strategy {
96            MLPredictedStrategy::HighParallelism => self.aggressive_parallelization(graph)?,
97            MLPredictedStrategy::BalancedParallelism => {
98                self.hybrid_parallelization(circuit, graph)?
99            }
100            MLPredictedStrategy::ConservativeParallelism => {
101                self.dependency_based_parallelization(graph)?
102            }
103            MLPredictedStrategy::LayerOptimized => self.layer_based_parallelization(graph)?,
104        };
105        let optimized_tasks = self.ml_optimize_tasks(task_groups, &features)?;
106        Ok(optimized_tasks)
107    }
108    /// Hardware-aware parallelization strategy
109    pub(super) fn hardware_aware_parallelization<const N: usize>(
110        &self,
111        circuit: &Circuit<N>,
112        graph: &DependencyGraph,
113    ) -> QuantRS2Result<Vec<ParallelTask>> {
114        let hw_char = Self::detect_hardware_characteristics();
115        let tasks = match self.select_hardware_strategy(&hw_char, circuit, graph)? {
116            HardwareStrategy::CacheOptimized => {
117                self.cache_optimized_parallelization(graph, &hw_char)?
118            }
119            HardwareStrategy::SIMDOptimized => {
120                self.simd_optimized_parallelization(graph, &hw_char)?
121            }
122            HardwareStrategy::NUMAAware => self.numa_aware_parallelization(graph, &hw_char)?,
123            HardwareStrategy::GPUOffload => self.dependency_based_parallelization(graph)?,
124            HardwareStrategy::Hybrid => self.hybrid_hardware_parallelization(graph, &hw_char)?,
125        };
126        let optimized_tasks = Self::optimize_hardware_affinity(tasks, &hw_char)?;
127        Ok(optimized_tasks)
128    }
129    /// Calculate parallelization metrics
130    pub(super) fn calculate_parallelization_metrics<const N: usize>(
131        &self,
132        circuit: &Circuit<N>,
133        graph: &DependencyGraph,
134        tasks: Vec<ParallelTask>,
135    ) -> QuantRS2Result<ParallelizationAnalysis> {
136        let num_layers = graph.layers.len();
137        let max_parallelism = graph
138            .layers
139            .iter()
140            .map(std::vec::Vec::len)
141            .max()
142            .unwrap_or(1);
143        let critical_path_length = graph.layers.len();
144        let efficiency = if circuit.num_gates() > 0 {
145            max_parallelism as f64 / circuit.num_gates() as f64
146        } else {
147            0.0
148        };
149        let resource_utilization = ResourceUtilization {
150            cpu_utilization: vec![0.8; self.config.max_threads],
151            memory_usage: vec![
152                self.config.memory_budget / self.config.max_threads;
153                self.config.max_threads
154            ],
155            load_balance_score: 0.85,
156            communication_overhead: 0.1,
157        };
158        let recommendations = self.generate_optimization_recommendations(circuit, graph, &tasks);
159        Ok(ParallelizationAnalysis {
160            tasks,
161            num_layers,
162            efficiency,
163            max_parallelism,
164            critical_path_length,
165            resource_utilization,
166            recommendations,
167        })
168    }
169    /// Update performance statistics
170    pub(super) fn update_performance_stats(
171        &self,
172        execution_time: Duration,
173        analysis: &ParallelizationAnalysis,
174    ) {
175        let mut stats = self
176            .performance_stats
177            .lock()
178            .expect("performance stats mutex should not be poisoned");
179        stats.circuits_processed += 1;
180        stats.total_execution_time += execution_time;
181        stats.average_efficiency = stats
182            .average_efficiency
183            .mul_add((stats.circuits_processed - 1) as f64, analysis.efficiency)
184            / stats.circuits_processed as f64;
185    }
186}