1use crate::{
8 error::{QuantRS2Error, QuantRS2Result},
9 tensor_network::Tensor,
10};
11use num_complex::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.6 * memory_score + 0.4 * compute_score
221 }
222 SimulationTaskType::TensorContraction => {
223 0.3 * memory_score + 0.7 * compute_score
225 }
226 SimulationTaskType::Distributed => {
227 0.5 * 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.performance_monitor.read().unwrap();
277 let memory_manager = self.memory_manager.lock().unwrap();
278
279 LargeScalePerformanceStats {
280 contraction_stats: monitor.contraction_stats.clone(),
281 state_vector_stats: monitor.state_vector_stats.clone(),
282 total_memory_allocated: memory_manager.get_total_allocated(),
283 peak_memory_usage: memory_manager.get_peak_usage(),
284 device_utilization: self.compute_device_utilization(),
285 }
286 }
287
288 fn compute_device_utilization(&self) -> Vec<f64> {
289 self.devices
291 .iter()
292 .enumerate()
293 .map(|(i, _)| {
294 if Some(i) == self.active_device {
295 85.0
296 } else {
297 0.0
298 }
299 })
300 .collect()
301 }
302}
303
304#[derive(Debug, Clone)]
305pub enum SimulationTaskType {
306 StateVector,
307 TensorContraction,
308 Distributed,
309}
310
311#[derive(Debug)]
313pub struct LargeScaleStateVectorSim {
314 num_qubits: usize,
315 device_id: usize,
316 state_allocation_id: Option<u64>,
317 temp_allocation_id: Option<u64>,
318 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
319 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
320}
321
322impl LargeScaleStateVectorSim {
323 fn new(
324 num_qubits: usize,
325 device_id: usize,
326 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
327 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
328 ) -> QuantRS2Result<Self> {
329 let state_size = 1_usize << num_qubits;
330 let buffer_size = state_size * std::mem::size_of::<Complex64>();
331
332 let (state_allocation, temp_allocation) = {
333 let mut mm = memory_manager.lock().unwrap();
334 let state_allocation =
335 mm.allocate(device_id, buffer_size, AllocationType::StateVector)?;
336 let temp_allocation =
337 mm.allocate(device_id, buffer_size, AllocationType::IntermediateBuffer)?;
338 (state_allocation, temp_allocation)
339 };
340
341 Ok(Self {
342 num_qubits,
343 device_id,
344 state_allocation_id: Some(state_allocation),
345 temp_allocation_id: Some(temp_allocation),
346 memory_manager,
347 performance_monitor,
348 })
349 }
350
351 pub fn initialize_state(&mut self, initial_amplitudes: &[Complex64]) -> QuantRS2Result<()> {
353 let expected_size = 1_usize << self.num_qubits;
354 if initial_amplitudes.len() != expected_size {
355 return Err(QuantRS2Error::InvalidInput(format!(
356 "Expected {} amplitudes, got {}",
357 expected_size,
358 initial_amplitudes.len()
359 )));
360 }
361
362 let start_time = std::time::Instant::now();
363
364 std::thread::sleep(std::time::Duration::from_micros(100));
366
367 let duration = start_time.elapsed().as_millis() as f64;
368 self.performance_monitor
369 .write()
370 .unwrap()
371 .record_operation("state_initialization", duration);
372
373 Ok(())
374 }
375
376 pub fn apply_gate_optimized(
378 &mut self,
379 gate_type: LargeScaleGateType,
380 qubits: &[usize],
381 _parameters: &[f64],
382 ) -> QuantRS2Result<()> {
383 let start_time = std::time::Instant::now();
384
385 let complexity = match gate_type {
387 LargeScaleGateType::SingleQubit => 1.0,
388 LargeScaleGateType::TwoQubit => 2.0,
389 LargeScaleGateType::MultiQubit => qubits.len() as f64,
390 LargeScaleGateType::Parameterized => 1.5,
391 };
392
393 let simulation_time = (complexity * 10.0) as u64;
394 std::thread::sleep(std::time::Duration::from_micros(simulation_time));
395
396 let duration = start_time.elapsed().as_millis() as f64;
397
398 let mut monitor = self.performance_monitor.write().unwrap();
399 monitor.record_operation(&format!("{:?}_gate", gate_type), duration);
400 monitor.state_vector_stats.total_gate_applications += 1;
401
402 Ok(())
403 }
404
405 pub fn get_probabilities_gpu(&self) -> QuantRS2Result<Vec<f64>> {
407 let state_size = 1_usize << self.num_qubits;
408 let start_time = std::time::Instant::now();
409
410 std::thread::sleep(std::time::Duration::from_micros(50));
412
413 let mut probabilities = vec![0.0; state_size];
415 if !probabilities.is_empty() {
416 probabilities[0] = 1.0; }
418
419 let duration = start_time.elapsed().as_millis() as f64;
420 self.performance_monitor
421 .write()
422 .unwrap()
423 .record_operation("probability_calculation", duration);
424
425 Ok(probabilities)
426 }
427
428 pub fn expectation_value_gpu(
430 &self,
431 observable: &LargeScaleObservable,
432 ) -> QuantRS2Result<Complex64> {
433 let start_time = std::time::Instant::now();
434
435 let complexity = match observable {
437 LargeScaleObservable::PauliString(_) => 1.0,
438 LargeScaleObservable::Hamiltonian(_) => 3.0,
439 LargeScaleObservable::CustomOperator(_) => 2.0,
440 };
441
442 let simulation_time = (complexity * 25.0) as u64;
443 std::thread::sleep(std::time::Duration::from_micros(simulation_time));
444
445 let duration = start_time.elapsed().as_millis() as f64;
446 self.performance_monitor
447 .write()
448 .unwrap()
449 .record_operation("expectation_value", duration);
450
451 Ok(Complex64::new(0.5, 0.0))
453 }
454}
455
456#[derive(Debug, Clone)]
457pub enum LargeScaleGateType {
458 SingleQubit,
459 TwoQubit,
460 MultiQubit,
461 Parameterized,
462}
463
464#[derive(Debug, Clone)]
465pub enum LargeScaleObservable {
466 PauliString(String),
467 Hamiltonian(Vec<(f64, String)>),
468 CustomOperator(String),
469}
470
471pub struct LargeScaleTensorContractor {
473 device_id: usize,
474 config: LargeScaleSimConfig,
475 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
476 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
477 tensor_cache: HashMap<usize, u64>, }
479
480impl LargeScaleTensorContractor {
481 fn new(
482 device_id: usize,
483 config: &LargeScaleSimConfig,
484 memory_manager: Arc<Mutex<LargeScaleMemoryManager>>,
485 performance_monitor: Arc<RwLock<LargeScalePerformanceMonitor>>,
486 ) -> QuantRS2Result<Self> {
487 Ok(Self {
488 device_id,
489 config: config.clone(),
490 memory_manager,
491 performance_monitor,
492 tensor_cache: HashMap::new(),
493 })
494 }
495
496 pub fn upload_tensor_optimized(&mut self, tensor: &Tensor) -> QuantRS2Result<()> {
498 let tensor_size = tensor.data.len() * std::mem::size_of::<Complex64>();
499
500 if tensor_size < self.config.gpu_tensor_threshold {
501 return Ok(());
503 }
504
505 let start_time = std::time::Instant::now();
506
507 let mut mm = self.memory_manager.lock().unwrap();
508 let allocation_id = mm.allocate(self.device_id, tensor_size, AllocationType::TensorData)?;
509
510 self.tensor_cache.insert(tensor.id, allocation_id);
511
512 std::thread::sleep(std::time::Duration::from_micros(tensor_size as u64 / 1000));
514
515 let duration = start_time.elapsed().as_millis() as f64;
516 self.performance_monitor
517 .write()
518 .unwrap()
519 .record_operation("tensor_upload", duration);
520
521 Ok(())
522 }
523
524 pub fn contract_optimized(
526 &mut self,
527 tensor1_id: usize,
528 tensor2_id: usize,
529 contract_indices: &[(usize, usize)],
530 ) -> QuantRS2Result<Tensor> {
531 let start_time = std::time::Instant::now();
532
533 let _tensor1_on_gpu = self.tensor_cache.contains_key(&tensor1_id);
535 let _tensor2_on_gpu = self.tensor_cache.contains_key(&tensor2_id);
536
537 let contraction_complexity = contract_indices.len() as f64 * 100.0;
539 let simulation_time = contraction_complexity as u64;
540 std::thread::sleep(std::time::Duration::from_micros(simulation_time));
541
542 let duration = start_time.elapsed().as_millis() as f64;
543
544 let mut monitor = self.performance_monitor.write().unwrap();
545 monitor.record_operation("tensor_contraction", duration);
546 monitor.contraction_stats.total_contractions += 1;
547 monitor.contraction_stats.total_contraction_time_ms += duration;
548
549 let result_data = ndarray::Array::from_shape_vec(
551 ndarray::IxDyn(&[2, 2]),
552 vec![
553 Complex64::new(1.0, 0.0),
554 Complex64::new(0.0, 0.0),
555 Complex64::new(0.0, 0.0),
556 Complex64::new(1.0, 0.0),
557 ],
558 )
559 .map_err(|e| QuantRS2Error::InvalidInput(format!("Tensor creation failed: {}", e)))?;
560
561 Ok(Tensor::new(
562 tensor1_id + tensor2_id, result_data,
564 vec!["result_i".to_string(), "result_j".to_string()],
565 ))
566 }
567
568 pub fn decompose_tensor_gpu(
570 &mut self,
571 tensor_id: usize,
572 decomp_type: TensorDecompositionType,
573 ) -> QuantRS2Result<TensorDecomposition> {
574 let start_time = std::time::Instant::now();
575
576 let decomp_complexity = match decomp_type {
578 TensorDecompositionType::SVD => 500.0,
579 TensorDecompositionType::QR => 300.0,
580 TensorDecompositionType::Eigenvalue => 400.0,
581 };
582
583 std::thread::sleep(std::time::Duration::from_micros(decomp_complexity as u64));
584
585 let duration = start_time.elapsed().as_millis() as f64;
586
587 let mut monitor = self.performance_monitor.write().unwrap();
588 monitor.record_operation(&format!("{:?}_decomposition", decomp_type), duration);
589 monitor.contraction_stats.decompositions_performed += 1;
590
591 Ok(TensorDecomposition {
592 decomposition_type: decomp_type,
593 factors: vec![tensor_id + 1000, tensor_id + 2000], singular_values: vec![1.0, 0.5, 0.1],
595 error_estimate: 1e-15,
596 })
597 }
598}
599
600#[derive(Debug, Clone)]
601pub enum TensorDecompositionType {
602 SVD,
603 QR,
604 Eigenvalue,
605}
606
607#[derive(Debug, Clone)]
608pub struct TensorDecomposition {
609 pub decomposition_type: TensorDecompositionType,
610 pub factors: Vec<usize>,
611 pub singular_values: Vec<f64>,
612 pub error_estimate: f64,
613}
614
615#[derive(Debug, Clone)]
616pub struct LargeScalePerformanceStats {
617 pub contraction_stats: ContractionStatistics,
618 pub state_vector_stats: StateVectorStatistics,
619 pub total_memory_allocated: usize,
620 pub peak_memory_usage: usize,
621 pub device_utilization: Vec<f64>,
622}
623
624impl LargeScaleMemoryManager {
625 fn new(devices: &[GpuDevice], config: &LargeScaleSimConfig) -> QuantRS2Result<Self> {
626 let mut memory_pools = HashMap::new();
627
628 for (i, device) in devices.iter().enumerate() {
629 let pool = MemoryPool {
630 device_id: i,
631 total_size: config.memory_pool_size.min(device.memory_size),
632 used_size: 0,
633 free_blocks: vec![MemoryBlock {
634 offset: 0,
635 size: config.memory_pool_size.min(device.memory_size),
636 is_pinned: false,
637 }],
638 allocated_blocks: HashMap::new(),
639 };
640 memory_pools.insert(i, pool);
641 }
642
643 Ok(Self {
644 memory_pools,
645 allocations: HashMap::new(),
646 next_allocation_id: 1,
647 })
648 }
649
650 fn allocate(
651 &mut self,
652 device_id: usize,
653 size: usize,
654 alloc_type: AllocationType,
655 ) -> QuantRS2Result<u64> {
656 let pool = self.memory_pools.get_mut(&device_id).ok_or_else(|| {
657 QuantRS2Error::InvalidParameter(format!("Device {} not found", device_id))
658 })?;
659
660 let mut best_block_idx = None;
662 let mut best_size = usize::MAX;
663
664 for (i, block) in pool.free_blocks.iter().enumerate() {
665 if block.size >= size && block.size < best_size {
666 best_size = block.size;
667 best_block_idx = Some(i);
668 }
669 }
670
671 let block_idx = best_block_idx
672 .ok_or_else(|| QuantRS2Error::RuntimeError("Insufficient GPU memory".to_string()))?;
673
674 let block = pool.free_blocks.remove(block_idx);
675 let allocation_id = self.next_allocation_id;
676 self.next_allocation_id += 1;
677
678 let allocated_block = MemoryBlock {
680 offset: block.offset,
681 size,
682 is_pinned: false,
683 };
684
685 pool.allocated_blocks.insert(allocation_id, allocated_block);
686 pool.used_size += size;
687
688 if block.size > size {
690 pool.free_blocks.push(MemoryBlock {
691 offset: block.offset + size,
692 size: block.size - size,
693 is_pinned: false,
694 });
695 }
696
697 self.allocations.insert(
698 allocation_id,
699 AllocationInfo {
700 device_id,
701 size,
702 allocation_type: alloc_type,
703 timestamp: std::time::Instant::now(),
704 },
705 );
706
707 Ok(allocation_id)
708 }
709
710 fn get_total_allocated(&self) -> usize {
711 self.allocations.values().map(|info| info.size).sum()
712 }
713
714 fn get_peak_usage(&self) -> usize {
715 self.memory_pools
716 .values()
717 .map(|pool| pool.used_size)
718 .max()
719 .unwrap_or(0)
720 }
721}
722
723impl LargeScalePerformanceMonitor {
724 fn new() -> Self {
725 Self {
726 operation_times: HashMap::new(),
727 memory_usage_history: Vec::new(),
728 contraction_stats: ContractionStatistics::default(),
729 state_vector_stats: StateVectorStatistics::default(),
730 }
731 }
732
733 fn record_operation(&mut self, operation: &str, duration_ms: f64) {
734 self.operation_times
735 .entry(operation.to_string())
736 .or_insert_with(Vec::new)
737 .push(duration_ms);
738 }
739}
740
741#[cfg(test)]
742mod tests {
743 use super::*;
744
745 fn create_test_devices() -> Vec<GpuDevice> {
746 vec![
747 GpuDevice {
748 id: 0,
749 name: "Test GPU 1".to_string(),
750 backend: GpuBackend::CUDA,
751 memory_size: 8 * 1024 * 1024 * 1024, compute_units: 64,
753 max_work_group_size: 1024,
754 supports_double_precision: true,
755 is_available: true,
756 },
757 GpuDevice {
758 id: 1,
759 name: "Test GPU 2".to_string(),
760 backend: GpuBackend::CUDA,
761 memory_size: 16 * 1024 * 1024 * 1024, compute_units: 128,
763 max_work_group_size: 1024,
764 supports_double_precision: true,
765 is_available: true,
766 },
767 ]
768 }
769
770 #[test]
771 fn test_large_scale_accelerator_creation() {
772 let config = LargeScaleSimConfig::default();
773 let devices = create_test_devices();
774
775 let accelerator = LargeScaleSimAccelerator::new(config, devices);
776 assert!(accelerator.is_ok());
777 }
778
779 #[test]
780 fn test_device_selection() {
781 let config = LargeScaleSimConfig::default();
782 let devices = create_test_devices();
783
784 let mut accelerator = LargeScaleSimAccelerator::new(config, devices).unwrap();
785
786 let device_id = accelerator.select_optimal_device(
788 SimulationTaskType::StateVector,
789 1024 * 1024 * 1024, );
791
792 assert!(device_id.is_ok());
793 assert!(device_id.unwrap() < 2);
794 }
795
796 #[test]
797 fn test_state_vector_simulation() {
798 let config = LargeScaleSimConfig::default();
799 let devices = create_test_devices();
800
801 let mut accelerator = LargeScaleSimAccelerator::new(config, devices).unwrap();
802 let state_sim = accelerator.init_state_vector_simulation(5);
803
804 assert!(state_sim.is_ok());
805
806 let mut sim = state_sim.unwrap();
807
808 let initial_state = vec![Complex64::new(1.0, 0.0); 32]; assert!(sim.initialize_state(&initial_state).is_ok());
811
812 assert!(sim
814 .apply_gate_optimized(
815 LargeScaleGateType::SingleQubit,
816 &[0],
817 &[std::f64::consts::PI / 2.0]
818 )
819 .is_ok());
820 }
821
822 #[test]
823 fn test_tensor_contractor() {
824 let config = LargeScaleSimConfig::default();
825 let devices = create_test_devices();
826
827 let mut accelerator = LargeScaleSimAccelerator::new(config, devices).unwrap();
828 let contractor = accelerator.init_tensor_contractor();
829
830 assert!(contractor.is_ok());
831
832 let mut contractor = contractor.unwrap();
833
834 let data = ndarray::Array::from_shape_vec(
836 ndarray::IxDyn(&[2, 2]),
837 vec![
838 Complex64::new(1.0, 0.0),
839 Complex64::new(0.0, 0.0),
840 Complex64::new(0.0, 0.0),
841 Complex64::new(1.0, 0.0),
842 ],
843 )
844 .unwrap();
845
846 let tensor = Tensor::new(0, data, vec!["i".to_string(), "j".to_string()]);
847
848 assert!(contractor.upload_tensor_optimized(&tensor).is_ok());
850
851 let result = contractor.contract_optimized(0, 1, &[(0, 1)]);
853 assert!(result.is_ok());
854 }
855
856 #[test]
857 fn test_memory_management() {
858 let config = LargeScaleSimConfig::default();
859 let devices = create_test_devices();
860
861 let memory_manager = LargeScaleMemoryManager::new(&devices, &config);
862 assert!(memory_manager.is_ok());
863
864 let mut mm = memory_manager.unwrap();
865
866 let allocation = mm.allocate(0, 1024, AllocationType::StateVector);
868 assert!(allocation.is_ok());
869
870 assert_eq!(mm.get_total_allocated(), 1024);
872 }
873
874 #[test]
875 fn test_performance_monitoring() {
876 let config = LargeScaleSimConfig::default();
877 let devices = create_test_devices();
878
879 let accelerator = LargeScaleSimAccelerator::new(config, devices).unwrap();
880
881 {
883 let mut monitor = accelerator.performance_monitor.write().unwrap();
884 monitor.record_operation("test_operation", 10.5);
885 monitor.record_operation("test_operation", 12.3);
886 }
887
888 let stats = accelerator.get_performance_stats();
889 assert_eq!(stats.total_memory_allocated, 0); }
891
892 #[test]
893 fn test_large_qubit_simulation_limit() {
894 let config = LargeScaleSimConfig::default();
895 let devices = create_test_devices();
896
897 let mut accelerator = LargeScaleSimAccelerator::new(config, devices).unwrap();
898
899 let result = accelerator.init_state_vector_simulation(100);
901 assert!(result.is_err());
902 assert!(matches!(
903 result.unwrap_err(),
904 QuantRS2Error::UnsupportedQubits(_, _)
905 ));
906 }
907
908 #[test]
909 fn test_tensor_decomposition() {
910 let config = LargeScaleSimConfig::default();
911 let devices = create_test_devices();
912
913 let mut accelerator = LargeScaleSimAccelerator::new(config, devices).unwrap();
914 let mut contractor = accelerator.init_tensor_contractor().unwrap();
915
916 let decomp_result = contractor.decompose_tensor_gpu(0, TensorDecompositionType::SVD);
917 assert!(decomp_result.is_ok());
918
919 let decomp = decomp_result.unwrap();
920 assert_eq!(decomp.factors.len(), 2);
921 assert!(!decomp.singular_values.is_empty());
922 }
923}