1use crate::{
8 error::{QuantRS2Error, QuantRS2Result},
9 tensor_network::Tensor,
10};
11use scirs2_core::Complex64;
12use std::{
13 collections::HashMap,
14 sync::{Arc, Mutex, RwLock},
15};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum GpuBackend {
20 CPU,
21 CUDA,
22 OpenCL,
23 ROCm,
24 WebGPU,
25 Metal,
26 Vulkan,
27}
28
29#[derive(Debug, Clone)]
31pub struct GpuDevice {
32 pub id: u32,
33 pub name: String,
34 pub backend: GpuBackend,
35 pub memory_size: usize,
36 pub compute_units: u32,
37 pub max_work_group_size: usize,
38 pub supports_double_precision: bool,
39 pub is_available: bool,
40}
41
42#[derive(Debug, Clone)]
44pub struct LargeScaleSimConfig {
45 pub max_state_vector_qubits: usize,
47 pub gpu_tensor_threshold: usize,
49 pub memory_pool_size: usize,
51 pub enable_distributed: bool,
53 pub tensor_decomp_threshold: f64,
55 pub use_double_precision: bool,
57}
58
59impl Default for LargeScaleSimConfig {
60 fn default() -> Self {
61 Self {
62 max_state_vector_qubits: 50,
63 gpu_tensor_threshold: 1024,
64 memory_pool_size: 8 * 1024 * 1024 * 1024, enable_distributed: false,
66 tensor_decomp_threshold: 1e-12,
67 use_double_precision: true,
68 }
69 }
70}
71
72pub struct LargeScaleSimAccelerator {
74 config: LargeScaleSimConfig,
75 devices: Vec<GpuDevice>,
76 active_device: Option<usize>,
77 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
78 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
79}
80
81#[derive(Debug)]
83pub struct LargeScaleMemoryManager {
84 memory_pools: HashMap<usize, MemoryPool>,
86 allocations: HashMap<u64, AllocationInfo>,
88 next_allocation_id: u64,
90}
91
92#[derive(Debug)]
93pub struct MemoryPool {
94 device_id: usize,
95 total_size: usize,
96 used_size: usize,
97 free_blocks: Vec<MemoryBlock>,
98 allocated_blocks: HashMap<u64, MemoryBlock>,
99}
100
101#[derive(Debug, Clone)]
102pub struct MemoryBlock {
103 offset: usize,
104 size: usize,
105 is_pinned: bool,
106}
107
108#[derive(Debug)]
109pub struct AllocationInfo {
110 device_id: usize,
111 size: usize,
112 allocation_type: AllocationType,
113 timestamp: std::time::Instant,
114}
115
116#[derive(Debug, Clone)]
117pub enum AllocationType {
118 StateVector,
119 TensorData,
120 IntermediateBuffer,
121 TemporaryStorage,
122}
123
124#[derive(Debug)]
126pub struct LargeScalePerformanceMonitor {
127 operation_times: HashMap<String, Vec<f64>>,
129 memory_usage_history: Vec<(std::time::Instant, usize)>,
131 contraction_stats: ContractionStatistics,
133 state_vector_stats: StateVectorStatistics,
135}
136
137#[derive(Debug, Default, Clone)]
138pub struct ContractionStatistics {
139 pub total_contractions: u64,
140 pub total_contraction_time_ms: f64,
141 pub largest_tensor_size: usize,
142 pub decompositions_performed: u64,
143 pub memory_savings_percent: f64,
144}
145
146#[derive(Debug, Default, Clone)]
147pub struct StateVectorStatistics {
148 pub max_qubits_simulated: usize,
149 pub total_gate_applications: u64,
150 pub total_simulation_time_ms: f64,
151 pub memory_transfer_overhead_percent: f64,
152 pub gpu_utilization_percent: f64,
153}
154
155impl LargeScaleSimAccelerator {
156 pub fn new(config: LargeScaleSimConfig, devices: Vec<GpuDevice>) -> QuantRS2Result<Self> {
158 if devices.is_empty() {
159 return Err(QuantRS2Error::NoHardwareAvailable(
160 "No GPU devices available for large-scale simulation".to_string(),
161 ));
162 }
163
164 let memory_manager = Arc::new(Mutex::new(LargeScaleMemoryManager::new(&devices, &config)?));
165 let performance_monitor = Arc::new(RwLock::new(LargeScalePerformanceMonitor::new()));
166
167 Ok(Self {
168 config,
169 active_device: Some(0),
170 devices,
171 memory_manager,
172 performance_monitor,
173 })
174 }
175
176 pub fn select_optimal_device(
178 &mut self,
179 task_type: SimulationTaskType,
180 required_memory: usize,
181 ) -> QuantRS2Result<usize> {
182 let mut best_device_id = 0;
183 let mut best_score = 0.0;
184
185 for (i, device) in self.devices.iter().enumerate() {
186 if !device.is_available || device.memory_size < required_memory {
187 continue;
188 }
189
190 let score = self.compute_device_score(device, &task_type, required_memory);
191 if score > best_score {
192 best_score = score;
193 best_device_id = i;
194 }
195 }
196
197 if best_score == 0.0 {
198 return Err(QuantRS2Error::NoHardwareAvailable(
199 "No suitable device found for simulation task".to_string(),
200 ));
201 }
202
203 self.active_device = Some(best_device_id);
204 Ok(best_device_id)
205 }
206
207 fn compute_device_score(
208 &self,
209 device: &GpuDevice,
210 task_type: &SimulationTaskType,
211 required_memory: usize,
212 ) -> f64 {
213 let memory_score =
214 (device.memory_size - required_memory) as f64 / device.memory_size as f64;
215 let compute_score = device.compute_units as f64 / 100.0; match task_type {
218 SimulationTaskType::StateVector => {
219 0.6f64.mul_add(memory_score, 0.4 * compute_score)
221 }
222 SimulationTaskType::TensorContraction => {
223 0.3f64.mul_add(memory_score, 0.7 * compute_score)
225 }
226 SimulationTaskType::Distributed => {
227 0.5f64.mul_add(memory_score, 0.5 * compute_score)
229 }
230 }
231 }
232
233 pub fn init_state_vector_simulation(
235 &mut self,
236 num_qubits: usize,
237 ) -> QuantRS2Result<LargeScaleStateVectorSim> {
238 if num_qubits > self.config.max_state_vector_qubits {
239 return Err(QuantRS2Error::UnsupportedQubits(
240 num_qubits,
241 format!(
242 "Maximum {} qubits supported",
243 self.config.max_state_vector_qubits
244 ),
245 ));
246 }
247
248 let state_size = 1_usize << num_qubits;
249 let memory_required = state_size * std::mem::size_of::<Complex64>() * 2; let device_id =
252 self.select_optimal_device(SimulationTaskType::StateVector, memory_required)?;
253
254 LargeScaleStateVectorSim::new(
255 num_qubits,
256 device_id,
257 Arc::clone(&self.memory_manager),
258 Arc::clone(&self.performance_monitor),
259 )
260 }
261
262 pub fn init_tensor_contractor(&mut self) -> QuantRS2Result<LargeScaleTensorContractor> {
264 let device_id = self.active_device.unwrap_or(0);
265
266 LargeScaleTensorContractor::new(
267 device_id,
268 &self.config,
269 Arc::clone(&self.memory_manager),
270 Arc::clone(&self.performance_monitor),
271 )
272 }
273
274 pub fn get_performance_stats(&self) -> LargeScalePerformanceStats {
276 let monitor = self
277 .performance_monitor
278 .read()
279 .expect("Performance monitor lock poisoned");
280 let memory_manager = self
281 .memory_manager
282 .lock()
283 .expect("Memory manager lock poisoned");
284
285 LargeScalePerformanceStats {
286 contraction_stats: monitor.contraction_stats.clone(),
287 state_vector_stats: monitor.state_vector_stats.clone(),
288 total_memory_allocated: memory_manager.get_total_allocated(),
289 peak_memory_usage: memory_manager.get_peak_usage(),
290 device_utilization: self.compute_device_utilization(),
291 }
292 }
293
294 fn compute_device_utilization(&self) -> Vec<f64> {
295 self.devices
297 .iter()
298 .enumerate()
299 .map(|(i, _)| {
300 if Some(i) == self.active_device {
301 85.0
302 } else {
303 0.0
304 }
305 })
306 .collect()
307 }
308}
309
310#[derive(Debug, Clone)]
311pub enum SimulationTaskType {
312 StateVector,
313 TensorContraction,
314 Distributed,
315}
316
317#[derive(Debug)]
319pub struct LargeScaleStateVectorSim {
320 num_qubits: usize,
321 device_id: usize,
322 state_allocation_id: Option<u64>,
323 temp_allocation_id: Option<u64>,
324 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
325 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
326}
327
328impl LargeScaleStateVectorSim {
329 fn new(
330 num_qubits: usize,
331 device_id: usize,
332 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
333 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
334 ) -> QuantRS2Result<Self> {
335 let state_size = 1_usize << num_qubits;
336 let buffer_size = state_size * std::mem::size_of::<Complex64>();
337
338 let (state_allocation, temp_allocation) = {
339 let mut mm = memory_manager
340 .lock()
341 .expect("Memory manager lock poisoned during state vector init");
342 let state_allocation =
343 mm.allocate(device_id, buffer_size, AllocationType::StateVector)?;
344 let temp_allocation =
345 mm.allocate(device_id, buffer_size, AllocationType::IntermediateBuffer)?;
346 (state_allocation, temp_allocation)
347 };
348
349 Ok(Self {
350 num_qubits,
351 device_id,
352 state_allocation_id: Some(state_allocation),
353 temp_allocation_id: Some(temp_allocation),
354 memory_manager,
355 performance_monitor,
356 })
357 }
358
359 pub fn initialize_state(&mut self, initial_amplitudes: &[Complex64]) -> QuantRS2Result<()> {
361 let expected_size = 1_usize << self.num_qubits;
362 if initial_amplitudes.len() != expected_size {
363 return Err(QuantRS2Error::InvalidInput(format!(
364 "Expected {} amplitudes, got {}",
365 expected_size,
366 initial_amplitudes.len()
367 )));
368 }
369
370 let start_time = std::time::Instant::now();
371
372 std::thread::sleep(std::time::Duration::from_micros(100));
374
375 let duration = start_time.elapsed().as_millis() as f64;
376 self.performance_monitor
377 .write()
378 .expect("Performance monitor lock poisoned during state initialization")
379 .record_operation("state_initialization", duration);
380
381 Ok(())
382 }
383
384 pub fn apply_gate_optimized(
386 &mut self,
387 gate_type: LargeScaleGateType,
388 qubits: &[usize],
389 _parameters: &[f64],
390 ) -> QuantRS2Result<()> {
391 let start_time = std::time::Instant::now();
392
393 let complexity = match gate_type {
395 LargeScaleGateType::SingleQubit => 1.0,
396 LargeScaleGateType::TwoQubit => 2.0,
397 LargeScaleGateType::MultiQubit => qubits.len() as f64,
398 LargeScaleGateType::Parameterized => 1.5,
399 };
400
401 let simulation_time = (complexity * 10.0) as u64;
402 std::thread::sleep(std::time::Duration::from_micros(simulation_time));
403
404 let duration = start_time.elapsed().as_millis() as f64;
405
406 let mut monitor = self
407 .performance_monitor
408 .write()
409 .expect("Performance monitor lock poisoned during gate application");
410 monitor.record_operation(&format!("{gate_type:?}_gate"), duration);
411 monitor.state_vector_stats.total_gate_applications += 1;
412
413 Ok(())
414 }
415
416 pub fn get_probabilities_gpu(&self) -> QuantRS2Result<Vec<f64>> {
418 let state_size = 1_usize << self.num_qubits;
419 let start_time = std::time::Instant::now();
420
421 std::thread::sleep(std::time::Duration::from_micros(50));
423
424 let mut probabilities = vec![0.0; state_size];
426 if !probabilities.is_empty() {
427 probabilities[0] = 1.0; }
429
430 let duration = start_time.elapsed().as_millis() as f64;
431 self.performance_monitor
432 .write()
433 .expect("Performance monitor lock poisoned during probability calculation")
434 .record_operation("probability_calculation", duration);
435
436 Ok(probabilities)
437 }
438
439 pub fn expectation_value_gpu(
441 &self,
442 observable: &LargeScaleObservable,
443 ) -> QuantRS2Result<Complex64> {
444 let start_time = std::time::Instant::now();
445
446 let complexity = match observable {
448 LargeScaleObservable::PauliString(_) => 1.0,
449 LargeScaleObservable::Hamiltonian(_) => 3.0,
450 LargeScaleObservable::CustomOperator(_) => 2.0,
451 };
452
453 let simulation_time = (complexity * 25.0) as u64;
454 std::thread::sleep(std::time::Duration::from_micros(simulation_time));
455
456 let duration = start_time.elapsed().as_millis() as f64;
457 self.performance_monitor
458 .write()
459 .expect("Performance monitor lock poisoned during expectation value calculation")
460 .record_operation("expectation_value", duration);
461
462 Ok(Complex64::new(0.5, 0.0))
464 }
465}
466
467#[derive(Debug, Clone)]
468pub enum LargeScaleGateType {
469 SingleQubit,
470 TwoQubit,
471 MultiQubit,
472 Parameterized,
473}
474
475#[derive(Debug, Clone)]
476pub enum LargeScaleObservable {
477 PauliString(String),
478 Hamiltonian(Vec<(f64, String)>),
479 CustomOperator(String),
480}
481
482pub struct LargeScaleTensorContractor {
484 device_id: usize,
485 config: LargeScaleSimConfig,
486 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
487 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
488 tensor_cache: HashMap<usize, u64>, }
490
491impl LargeScaleTensorContractor {
492 fn new(
493 device_id: usize,
494 config: &LargeScaleSimConfig,
495 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
496 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
497 ) -> QuantRS2Result<Self> {
498 Ok(Self {
499 device_id,
500 config: config.clone(),
501 memory_manager,
502 performance_monitor,
503 tensor_cache: HashMap::new(),
504 })
505 }
506
507 pub fn upload_tensor_optimized(&mut self, tensor: &Tensor) -> QuantRS2Result<()> {
509 let tensor_size = tensor.data.len() * std::mem::size_of::<Complex64>();
510
511 if tensor_size < self.config.gpu_tensor_threshold {
512 return Ok(());
514 }
515
516 let start_time = std::time::Instant::now();
517
518 let mut mm = self
519 .memory_manager
520 .lock()
521 .expect("Memory manager lock poisoned during tensor upload");
522 let allocation_id = mm.allocate(self.device_id, tensor_size, AllocationType::TensorData)?;
523
524 self.tensor_cache.insert(tensor.id, allocation_id);
525
526 std::thread::sleep(std::time::Duration::from_micros(tensor_size as u64 / 1000));
528
529 let duration = start_time.elapsed().as_millis() as f64;
530 self.performance_monitor
531 .write()
532 .expect("Performance monitor lock poisoned during tensor upload")
533 .record_operation("tensor_upload", duration);
534
535 Ok(())
536 }
537
538 pub fn contract_optimized(
540 &mut self,
541 tensor1_id: usize,
542 tensor2_id: usize,
543 contract_indices: &[(usize, usize)],
544 ) -> QuantRS2Result<Tensor> {
545 let start_time = std::time::Instant::now();
546
547 let _tensor1_on_gpu = self.tensor_cache.contains_key(&tensor1_id);
549 let _tensor2_on_gpu = self.tensor_cache.contains_key(&tensor2_id);
550
551 let contraction_complexity = contract_indices.len() as f64 * 100.0;
553 let simulation_time = contraction_complexity as u64;
554 std::thread::sleep(std::time::Duration::from_micros(simulation_time));
555
556 let duration = start_time.elapsed().as_millis() as f64;
557
558 let mut monitor = self
559 .performance_monitor
560 .write()
561 .expect("Performance monitor lock poisoned during tensor contraction");
562 monitor.record_operation("tensor_contraction", duration);
563 monitor.contraction_stats.total_contractions += 1;
564 monitor.contraction_stats.total_contraction_time_ms += duration;
565
566 let result_data = scirs2_core::ndarray::Array::from_shape_vec(
568 scirs2_core::ndarray::IxDyn(&[2, 2]),
569 vec![
570 Complex64::new(1.0, 0.0),
571 Complex64::new(0.0, 0.0),
572 Complex64::new(0.0, 0.0),
573 Complex64::new(1.0, 0.0),
574 ],
575 )
576 .map_err(|e| QuantRS2Error::InvalidInput(format!("Tensor creation failed: {e}")))?;
577
578 Ok(Tensor::new(
579 tensor1_id + tensor2_id, result_data,
581 vec!["result_i".to_string(), "result_j".to_string()],
582 ))
583 }
584
585 pub fn decompose_tensor_gpu(
587 &mut self,
588 tensor_id: usize,
589 decomp_type: TensorDecompositionType,
590 ) -> QuantRS2Result<TensorDecomposition> {
591 let start_time = std::time::Instant::now();
592
593 let decomp_complexity = match decomp_type {
595 TensorDecompositionType::SVD => 500.0,
596 TensorDecompositionType::QR => 300.0,
597 TensorDecompositionType::Eigenvalue => 400.0,
598 };
599
600 std::thread::sleep(std::time::Duration::from_micros(decomp_complexity as u64));
601
602 let duration = start_time.elapsed().as_millis() as f64;
603
604 let mut monitor = self
605 .performance_monitor
606 .write()
607 .expect("Performance monitor lock poisoned during tensor decomposition");
608 monitor.record_operation(&format!("{decomp_type:?}_decomposition"), duration);
609 monitor.contraction_stats.decompositions_performed += 1;
610
611 Ok(TensorDecomposition {
612 decomposition_type: decomp_type,
613 factors: vec![tensor_id + 1000, tensor_id + 2000], singular_values: vec![1.0, 0.5, 0.1],
615 error_estimate: 1e-15,
616 })
617 }
618}
619
620#[derive(Debug, Clone)]
621pub enum TensorDecompositionType {
622 SVD,
623 QR,
624 Eigenvalue,
625}
626
627#[derive(Debug, Clone)]
628pub struct TensorDecomposition {
629 pub decomposition_type: TensorDecompositionType,
630 pub factors: Vec<usize>,
631 pub singular_values: Vec<f64>,
632 pub error_estimate: f64,
633}
634
635#[derive(Debug, Clone)]
636pub struct LargeScalePerformanceStats {
637 pub contraction_stats: ContractionStatistics,
638 pub state_vector_stats: StateVectorStatistics,
639 pub total_memory_allocated: usize,
640 pub peak_memory_usage: usize,
641 pub device_utilization: Vec<f64>,
642}
643
644impl LargeScaleMemoryManager {
645 fn new(devices: &[GpuDevice], config: &LargeScaleSimConfig) -> QuantRS2Result<Self> {
646 let mut memory_pools = HashMap::new();
647
648 for (i, device) in devices.iter().enumerate() {
649 let pool = MemoryPool {
650 device_id: i,
651 total_size: config.memory_pool_size.min(device.memory_size),
652 used_size: 0,
653 free_blocks: vec![MemoryBlock {
654 offset: 0,
655 size: config.memory_pool_size.min(device.memory_size),
656 is_pinned: false,
657 }],
658 allocated_blocks: HashMap::new(),
659 };
660 memory_pools.insert(i, pool);
661 }
662
663 Ok(Self {
664 memory_pools,
665 allocations: HashMap::new(),
666 next_allocation_id: 1,
667 })
668 }
669
670 fn allocate(
671 &mut self,
672 device_id: usize,
673 size: usize,
674 alloc_type: AllocationType,
675 ) -> QuantRS2Result<u64> {
676 let pool = self.memory_pools.get_mut(&device_id).ok_or_else(|| {
677 QuantRS2Error::InvalidParameter(format!("Device {device_id} not found"))
678 })?;
679
680 let mut best_block_idx = None;
682 let mut best_size = usize::MAX;
683
684 for (i, block) in pool.free_blocks.iter().enumerate() {
685 if block.size >= size && block.size < best_size {
686 best_size = block.size;
687 best_block_idx = Some(i);
688 }
689 }
690
691 let block_idx = best_block_idx
692 .ok_or_else(|| QuantRS2Error::RuntimeError("Insufficient GPU memory".to_string()))?;
693
694 let block = pool.free_blocks.remove(block_idx);
695 let allocation_id = self.next_allocation_id;
696 self.next_allocation_id += 1;
697
698 let allocated_block = MemoryBlock {
700 offset: block.offset,
701 size,
702 is_pinned: false,
703 };
704
705 pool.allocated_blocks.insert(allocation_id, allocated_block);
706 pool.used_size += size;
707
708 if block.size > size {
710 pool.free_blocks.push(MemoryBlock {
711 offset: block.offset + size,
712 size: block.size - size,
713 is_pinned: false,
714 });
715 }
716
717 self.allocations.insert(
718 allocation_id,
719 AllocationInfo {
720 device_id,
721 size,
722 allocation_type: alloc_type,
723 timestamp: std::time::Instant::now(),
724 },
725 );
726
727 Ok(allocation_id)
728 }
729
730 fn get_total_allocated(&self) -> usize {
731 self.allocations.values().map(|info| info.size).sum()
732 }
733
734 fn get_peak_usage(&self) -> usize {
735 self.memory_pools
736 .values()
737 .map(|pool| pool.used_size)
738 .max()
739 .unwrap_or_default()
740 }
741}
742
743impl LargeScalePerformanceMonitor {
744 fn new() -> Self {
745 Self {
746 operation_times: HashMap::new(),
747 memory_usage_history: Vec::new(),
748 contraction_stats: ContractionStatistics::default(),
749 state_vector_stats: StateVectorStatistics::default(),
750 }
751 }
752
753 fn record_operation(&mut self, operation: &str, duration_ms: f64) {
754 self.operation_times
755 .entry(operation.to_string())
756 .or_insert_with(Vec::new)
757 .push(duration_ms);
758 }
759}
760
761#[cfg(test)]
762mod tests {
763 use super::*;
764
765 fn create_test_devices() -> Vec<GpuDevice> {
766 vec![
767 GpuDevice {
768 id: 0,
769 name: "Test GPU 1".to_string(),
770 backend: GpuBackend::CUDA,
771 memory_size: 8 * 1024 * 1024 * 1024, compute_units: 64,
773 max_work_group_size: 1024,
774 supports_double_precision: true,
775 is_available: true,
776 },
777 GpuDevice {
778 id: 1,
779 name: "Test GPU 2".to_string(),
780 backend: GpuBackend::CUDA,
781 memory_size: 16 * 1024 * 1024 * 1024, compute_units: 128,
783 max_work_group_size: 1024,
784 supports_double_precision: true,
785 is_available: true,
786 },
787 ]
788 }
789
790 #[test]
791 fn test_large_scale_accelerator_creation() {
792 let config = LargeScaleSimConfig::default();
793 let devices = create_test_devices();
794
795 let accelerator = LargeScaleSimAccelerator::new(config, devices);
796 assert!(accelerator.is_ok());
797 }
798
799 #[test]
800 fn test_device_selection() {
801 let config = LargeScaleSimConfig::default();
802 let devices = create_test_devices();
803
804 let mut accelerator = LargeScaleSimAccelerator::new(config, devices)
805 .expect("Failed to create accelerator for device selection test");
806
807 let device_id = accelerator.select_optimal_device(
809 SimulationTaskType::StateVector,
810 1024 * 1024 * 1024, );
812
813 assert!(device_id.is_ok());
814 assert!(device_id.expect("Device selection failed") < 2);
815 }
816
817 #[test]
818 fn test_state_vector_simulation() {
819 let config = LargeScaleSimConfig::default();
820 let devices = create_test_devices();
821
822 let mut accelerator =
823 LargeScaleSimAccelerator::new(config, devices).expect("Failed to create accelerator");
824 let state_sim = accelerator.init_state_vector_simulation(5);
825
826 assert!(state_sim.is_ok());
827
828 let mut sim = state_sim.expect("Failed to initialize state vector simulation");
829
830 let initial_state = vec![Complex64::new(1.0, 0.0); 32]; assert!(sim.initialize_state(&initial_state).is_ok());
833
834 assert!(sim
836 .apply_gate_optimized(
837 LargeScaleGateType::SingleQubit,
838 &[0],
839 &[std::f64::consts::PI / 2.0]
840 )
841 .is_ok());
842 }
843
844 #[test]
845 fn test_tensor_contractor() {
846 let config = LargeScaleSimConfig::default();
847 let devices = create_test_devices();
848
849 let mut accelerator =
850 LargeScaleSimAccelerator::new(config, devices).expect("Failed to create accelerator");
851 let contractor = accelerator.init_tensor_contractor();
852
853 assert!(contractor.is_ok());
854
855 let mut contractor = contractor.expect("Failed to initialize tensor contractor");
856
857 let data = scirs2_core::ndarray::Array::from_shape_vec(
859 scirs2_core::ndarray::IxDyn(&[2, 2]),
860 vec![
861 Complex64::new(1.0, 0.0),
862 Complex64::new(0.0, 0.0),
863 Complex64::new(0.0, 0.0),
864 Complex64::new(1.0, 0.0),
865 ],
866 )
867 .expect("Failed to create tensor data array");
868
869 let tensor = Tensor::new(0, data, vec!["i".to_string(), "j".to_string()]);
870
871 assert!(contractor.upload_tensor_optimized(&tensor).is_ok());
873
874 let result = contractor.contract_optimized(0, 1, &[(0, 1)]);
876 assert!(result.is_ok());
877 }
878
879 #[test]
880 fn test_memory_management() {
881 let config = LargeScaleSimConfig::default();
882 let devices = create_test_devices();
883
884 let memory_manager = LargeScaleMemoryManager::new(&devices, &config);
885 assert!(memory_manager.is_ok());
886
887 let mut mm = memory_manager.expect("Failed to create memory manager");
888
889 let allocation = mm.allocate(0, 1024, AllocationType::StateVector);
891 assert!(allocation.is_ok());
892
893 assert_eq!(mm.get_total_allocated(), 1024);
895 }
896
897 #[test]
898 fn test_performance_monitoring() {
899 let config = LargeScaleSimConfig::default();
900 let devices = create_test_devices();
901
902 let accelerator =
903 LargeScaleSimAccelerator::new(config, devices).expect("Failed to create accelerator");
904
905 {
907 let mut monitor = accelerator
908 .performance_monitor
909 .write()
910 .expect("Performance monitor lock poisoned in test");
911 monitor.record_operation("test_operation", 10.5);
912 monitor.record_operation("test_operation", 12.3);
913 }
914
915 let stats = accelerator.get_performance_stats();
916 assert_eq!(stats.total_memory_allocated, 0); }
918
919 #[test]
920 fn test_large_qubit_simulation_limit() {
921 let config = LargeScaleSimConfig::default();
922 let devices = create_test_devices();
923
924 let mut accelerator =
925 LargeScaleSimAccelerator::new(config, devices).expect("Failed to create accelerator");
926
927 let result = accelerator.init_state_vector_simulation(100);
929 assert!(result.is_err());
930 let err = result.expect_err("Expected UnsupportedQubits error");
931 assert!(matches!(err, QuantRS2Error::UnsupportedQubits(_, _)));
932 }
933
934 #[test]
935 fn test_tensor_decomposition() {
936 let config = LargeScaleSimConfig::default();
937 let devices = create_test_devices();
938
939 let mut accelerator =
940 LargeScaleSimAccelerator::new(config, devices).expect("Failed to create accelerator");
941 let mut contractor = accelerator
942 .init_tensor_contractor()
943 .expect("Failed to initialize tensor contractor");
944
945 let decomp_result = contractor.decompose_tensor_gpu(0, TensorDecompositionType::SVD);
946 assert!(decomp_result.is_ok());
947
948 let decomp = decomp_result.expect("Failed to decompose tensor");
949 assert_eq!(decomp.factors.len(), 2);
950 assert!(!decomp.singular_values.is_empty());
951 }
952}