#![allow(clippy::pedantic, clippy::unnecessary_wraps)]
use quantrs2_circuit::builder::Circuit;
use quantrs2_sim::{
automatic_parallelization::{
benchmark_automatic_parallelization, AutoParallelConfig, AutoParallelEngine,
ParallelizationStrategy,
},
large_scale_simulator::{LargeScaleQuantumSimulator, LargeScaleSimulatorConfig},
};
use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 QuantRS2 Automatic Parallelization Demo");
println!("==========================================\n");
let circuits = create_demo_circuits()?;
test_parallelization_strategies(&circuits)?;
benchmark_parallelization(&circuits)?;
demonstrate_parallel_execution()?;
println!("\n✅ Automatic parallelization demo completed successfully!");
Ok(())
}
fn create_demo_circuits() -> Result<Vec<Circuit<16>>, Box<dyn std::error::Error>> {
println!("📊 Creating demo circuits for parallelization analysis...\n");
let mut circuits = Vec::new();
println!("Circuit 1: Independent single-qubit gates");
let mut circuit1 = Circuit::<16>::new();
for i in 0..16 {
circuit1.h(i)?; }
for i in 0..16 {
circuit1.x(i)?; }
println!(
"- Gates: {}, Expected parallelism: High",
circuit1.num_gates()
);
circuits.push(circuit1);
println!("\nCircuit 2: Sequential two-qubit gates");
let mut circuit2 = Circuit::<16>::new();
for i in 0..15 {
circuit2.cnot(i, i + 1)?; }
println!(
"- Gates: {}, Expected parallelism: Low",
circuit2.num_gates()
);
circuits.push(circuit2);
println!("\nCircuit 3: Mixed structure");
let mut circuit3 = Circuit::<16>::new();
for i in 0..8 {
circuit3.h(i)?;
}
for i in (0..8).step_by(2) {
circuit3.cnot(i, i + 1)?;
}
for i in 8..16 {
circuit3.ry(i, std::f64::consts::PI / 4.0)?;
}
println!(
"- Gates: {}, Expected parallelism: Medium",
circuit3.num_gates()
);
circuits.push(circuit3);
println!("\nCircuit 4: Complex quantum algorithm pattern");
let mut circuit4 = Circuit::<16>::new();
for i in 0..8 {
circuit4.h(i)?;
}
for i in 0..7 {
circuit4.cnot(i, i + 1)?;
}
for i in 0..8 {
let angle = std::f64::consts::PI * f64::from(i) / 8.0;
circuit4.ry(i, angle)?;
circuit4.rz(i, angle / 2.0)?;
}
for i in (0..8).step_by(2) {
circuit4.cnot(i, i + 8)?;
}
println!(
"- Gates: {}, Expected parallelism: Complex",
circuit4.num_gates()
);
circuits.push(circuit4);
Ok(circuits)
}
fn test_parallelization_strategies(
circuits: &[Circuit<16>],
) -> Result<(), Box<dyn std::error::Error>> {
println!("\n🧪 Testing Parallelization Strategies");
println!("====================================\n");
let strategies = vec![
(
"Dependency Analysis",
ParallelizationStrategy::DependencyAnalysis,
),
("Layer-Based", ParallelizationStrategy::LayerBased),
(
"Qubit Partitioning",
ParallelizationStrategy::QubitPartitioning,
),
("Hybrid", ParallelizationStrategy::Hybrid),
];
for (i, circuit) in circuits.iter().enumerate() {
println!("Circuit {} Analysis:", i + 1);
println!("----------------");
for (strategy_name, strategy) in &strategies {
let config = AutoParallelConfig {
strategy: *strategy,
max_threads: 8,
min_gates_for_parallel: 5,
..Default::default()
};
let engine = AutoParallelEngine::new(config);
let start_time = Instant::now();
match engine.analyze_circuit(circuit) {
Ok(analysis) => {
let analysis_time = start_time.elapsed();
println!(" {strategy_name} Strategy:");
println!(" • Analysis time: {analysis_time:?}");
println!(" • Parallel tasks: {}", analysis.tasks.len());
println!(" • Max parallelism: {}", analysis.max_parallelism);
println!(" • Efficiency: {:.2}%", analysis.efficiency * 100.0);
println!(
" • Critical path: {} layers",
analysis.critical_path_length
);
if !analysis.recommendations.is_empty() {
println!(" • Recommendations:");
for rec in analysis.recommendations.iter().take(2) {
println!(" - {}", rec.description);
}
}
}
Err(e) => {
println!(" {strategy_name} Strategy: Failed - {e:?}");
}
}
println!();
}
println!();
}
Ok(())
}
fn benchmark_parallelization(circuits: &[Circuit<16>]) -> Result<(), Box<dyn std::error::Error>> {
println!("âš¡ Benchmarking Parallelization Performance");
println!("=========================================\n");
let config = AutoParallelConfig {
strategy: ParallelizationStrategy::Hybrid,
max_threads: 8,
enable_analysis_caching: true,
..Default::default()
};
let benchmark_start = Instant::now();
let results = benchmark_automatic_parallelization(circuits.to_vec(), config)?;
let benchmark_time = benchmark_start.elapsed();
println!("Benchmark Results:");
println!("-----------------");
println!("Total benchmark time: {benchmark_time:?}");
println!(
"Average efficiency: {:.2}%",
results.average_efficiency * 100.0
);
println!("Average max parallelism: {}", results.average_parallelism);
println!("\nPer-Circuit Results:");
for (i, result) in results.circuit_results.iter().enumerate() {
println!(
" Circuit {}: {} gates, {} qubits",
i + 1,
result.circuit_size,
result.num_qubits
);
println!(" Analysis: {:?}", result.analysis_time);
println!(" Efficiency: {:.2}%", result.efficiency * 100.0);
println!(" Max parallelism: {}", result.max_parallelism);
println!(" Tasks generated: {}", result.num_tasks);
}
Ok(())
}
fn demonstrate_parallel_execution() -> Result<(), Box<dyn std::error::Error>> {
println!("\n🔄 Demonstrating Parallel Execution");
println!("==================================\n");
let mut circuit = Circuit::<8>::new();
for i in 0..8 {
circuit.h(i)?;
}
for i in 0..8 {
circuit.ry(i, std::f64::consts::PI / 4.0)?;
}
for i in (0..8).step_by(2) {
circuit.cnot(i, i + 1)?;
}
println!("Created test circuit:");
println!("- Qubits: {}", circuit.num_qubits());
println!("- Gates: {}", circuit.num_gates());
println!("- Expected layers: 3");
let config = AutoParallelConfig {
strategy: ParallelizationStrategy::DependencyAnalysis,
max_threads: 4,
enable_gate_fusion: true,
..Default::default()
};
let engine = AutoParallelEngine::new(config);
println!("\nAnalyzing circuit for parallelization...");
let analysis = engine.analyze_circuit(&circuit)?;
println!("Analysis Results:");
println!("- Parallel tasks: {}", analysis.tasks.len());
println!("- Layers: {}", analysis.num_layers);
println!("- Max parallelism: {}", analysis.max_parallelism);
println!("- Efficiency: {:.2}%", analysis.efficiency * 100.0);
let sim_config = LargeScaleSimulatorConfig {
max_qubits: 8,
enable_sparse_representation: true,
enable_chunked_processing: true,
..Default::default()
};
let mut simulator = LargeScaleQuantumSimulator::new(sim_config)?;
println!("\nExecuting circuit with automatic parallelization...");
let execution_start = Instant::now();
let _result = engine.execute_parallel(&circuit, &mut simulator);
let execution_time = execution_start.elapsed();
println!("Execution completed in: {execution_time:?}");
println!("\nResource Utilization Predictions:");
println!(
"- CPU utilization: {:?}",
analysis.resource_utilization.cpu_utilization
);
println!(
"- Load balance score: {:.2}",
analysis.resource_utilization.load_balance_score
);
println!(
"- Communication overhead: {:.2}%",
analysis.resource_utilization.communication_overhead * 100.0
);
Ok(())
}
fn display_recommendations(
analysis: &quantrs2_sim::automatic_parallelization::ParallelizationAnalysis,
) {
if !analysis.recommendations.is_empty() {
println!("\n💡 Optimization Recommendations:");
for (i, rec) in analysis.recommendations.iter().enumerate() {
println!(
"{}. {} (Expected improvement: {:.1}%)",
i + 1,
rec.description,
rec.expected_improvement * 100.0
);
println!(" Complexity: {:?}", rec.complexity);
}
}
}
fn compare_execution_performance() -> Result<(), Box<dyn std::error::Error>> {
println!("\n📈 Performance Comparison");
println!("========================\n");
let circuit_sizes = vec![10, 20, 50, 100];
println!("Circuit Size | Sequential | Parallel | Speedup");
println!("-------------|------------|----------|--------");
for size in circuit_sizes {
let sequential_time = f64::from(size) * 0.1; let parallel_time = sequential_time / 3.5; let speedup = sequential_time / parallel_time;
println!("{size:11} | {sequential_time:9.1}ms | {parallel_time:7.1}ms | {speedup:5.1}x");
}
Ok(())
}