1use crate::error::{MLError, Result};
8use crate::optimization::OptimizationMethod;
9use crate::qcnn::PoolingType;
10use crate::qnn::{QNNLayerType, QuantumNeuralNetwork};
11use crate::quantum_transformer::{
12 QuantumAttentionType, QuantumTransformer, QuantumTransformerConfig,
13};
14use scirs2_core::ndarray::{s, Array1, Array2, Array3, Array4, Axis};
15use quantrs2_circuit::builder::{Circuit, Simulator};
16use quantrs2_core::gate::{multi::*, single::*, GateOp};
17use quantrs2_sim::statevector::StateVectorSimulator;
18use std::collections::HashMap;
19use std::f64::consts::PI;
20
21#[derive(Debug, Clone)]
23pub struct ConvolutionalConfig {
24 pub num_filters: usize,
26 pub kernel_size: usize,
28 pub stride: usize,
30 pub padding: usize,
32 pub quantum_kernel: bool,
34 pub circuit_depth: usize,
36}
37
38#[derive(Debug, Clone)]
40pub struct QuantumVisionConfig {
41 pub num_qubits: usize,
43
44 pub encoding_method: ImageEncodingMethod,
46
47 pub backbone: VisionBackbone,
49
50 pub task_config: VisionTaskConfig,
52
53 pub preprocessing: PreprocessingConfig,
55
56 pub quantum_enhancement: QuantumEnhancement,
58}
59
60#[derive(Debug, Clone)]
62pub enum ImageEncodingMethod {
63 AmplitudeEncoding,
65
66 AngleEncoding { basis: String },
68
69 FRQI,
71
72 NEQR { gray_levels: usize },
74
75 QPIE,
77
78 HierarchicalEncoding { levels: usize },
80}
81
82#[derive(Debug, Clone)]
84pub enum VisionBackbone {
85 QuantumCNN {
87 conv_layers: Vec<ConvolutionalConfig>,
88 pooling_type: PoolingType,
89 },
90
91 QuantumViT {
93 patch_size: usize,
94 embed_dim: usize,
95 num_heads: usize,
96 depth: usize,
97 },
98
99 HybridBackbone {
101 cnn_layers: usize,
102 transformer_layers: usize,
103 },
104
105 QuantumResNet {
107 blocks: Vec<ResidualBlock>,
108 skip_connections: bool,
109 },
110
111 QuantumEfficientNet {
113 width_coefficient: f64,
114 depth_coefficient: f64,
115 },
116}
117
118#[derive(Debug, Clone)]
120pub enum VisionTaskConfig {
121 Classification {
123 num_classes: usize,
124 multi_label: bool,
125 },
126
127 ObjectDetection {
129 num_classes: usize,
130 anchor_sizes: Vec<(usize, usize)>,
131 iou_threshold: f64,
132 },
133
134 Segmentation {
136 num_classes: usize,
137 output_stride: usize,
138 },
139
140 InstanceSegmentation {
142 num_classes: usize,
143 mask_resolution: (usize, usize),
144 },
145
146 FeatureExtraction { feature_dim: usize, normalize: bool },
148
149 Generation {
151 latent_dim: usize,
152 output_channels: usize,
153 },
154}
155
156#[derive(Debug, Clone)]
158pub struct PreprocessingConfig {
159 pub image_size: (usize, usize),
161
162 pub normalize: bool,
164 pub mean: Vec<f64>,
165 pub std: Vec<f64>,
166
167 pub augmentation: AugmentationConfig,
169
170 pub color_space: ColorSpace,
172}
173
174#[derive(Debug, Clone)]
176pub struct AugmentationConfig {
177 pub horizontal_flip: bool,
179
180 pub rotation_range: f64,
182
183 pub zoom_range: (f64, f64),
185
186 pub brightness_range: (f64, f64),
188
189 pub quantum_noise: bool,
191}
192
193#[derive(Debug, Clone)]
195pub enum ColorSpace {
196 RGB,
197 Grayscale,
198 HSV,
199 LAB,
200 YCbCr,
201}
202
203#[derive(Debug, Clone)]
205pub enum QuantumEnhancement {
206 Low,
208
209 Medium,
211
212 High,
214
215 Custom {
217 quantum_layers: Vec<usize>,
218 entanglement_strength: f64,
219 },
220}
221
222#[derive(Debug, Clone)]
224pub struct ResidualBlock {
225 pub channels: usize,
227
228 pub kernel_size: usize,
230
231 pub stride: usize,
233
234 pub quantum_conv: bool,
236}
237
238#[derive(Debug, Clone)]
240pub struct QuantumVisionPipeline {
241 config: QuantumVisionConfig,
243
244 encoder: QuantumImageEncoder,
246
247 backbone: Box<dyn VisionModel>,
249
250 task_head: Box<dyn TaskHead>,
252
253 feature_extractor: QuantumFeatureExtractor,
255
256 preprocessor: ImagePreprocessor,
258
259 metrics: VisionMetrics,
261}
262
263#[derive(Debug, Clone)]
265pub struct QuantumImageEncoder {
266 method: ImageEncodingMethod,
268
269 num_qubits: usize,
271
272 encoding_circuits: Vec<Circuit<16>>,
274
275 parameters: Array1<f64>,
277}
278
279pub trait VisionModel: std::fmt::Debug {
281 fn forward(&self, input: &Array4<f64>) -> Result<Array4<f64>>;
283
284 fn parameters(&self) -> &Array1<f64>;
286
287 fn update_parameters(&mut self, params: &Array1<f64>) -> Result<()>;
289
290 fn num_parameters(&self) -> usize;
292
293 fn clone_box(&self) -> Box<dyn VisionModel>;
295}
296
297impl Clone for Box<dyn VisionModel> {
298 fn clone(&self) -> Self {
299 self.clone_box()
300 }
301}
302
303pub trait TaskHead: std::fmt::Debug {
305 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput>;
307
308 fn parameters(&self) -> &Array1<f64>;
310
311 fn update_parameters(&mut self, params: &Array1<f64>) -> Result<()>;
313
314 fn clone_box(&self) -> Box<dyn TaskHead>;
316}
317
318impl Clone for Box<dyn TaskHead> {
319 fn clone(&self) -> Self {
320 self.clone_box()
321 }
322}
323
324#[derive(Debug, Clone)]
326pub enum TaskOutput {
327 Classification {
329 logits: Array2<f64>,
330 probabilities: Array2<f64>,
331 },
332
333 Detection {
335 boxes: Array3<f64>,
336 scores: Array2<f64>,
337 classes: Array2<usize>,
338 },
339
340 Segmentation {
342 masks: Array4<f64>,
343 class_scores: Array4<f64>,
344 },
345
346 Features {
348 features: Array2<f64>,
349 attention_maps: Option<Array4<f64>>,
350 },
351
352 Generation {
354 images: Array4<f64>,
355 latent_codes: Array2<f64>,
356 },
357}
358
359#[derive(Debug, Clone)]
361pub struct QuantumFeatureExtractor {
362 feature_dim: usize,
364
365 feature_circuit_params: Vec<Vec<f64>>,
367
368 transform_network: QuantumNeuralNetwork,
370
371 attention: QuantumSpatialAttention,
373}
374
375#[derive(Debug, Clone)]
377pub struct QuantumSpatialAttention {
378 num_heads: usize,
380
381 attention_dim: usize,
383
384 attention_circuit_params: Vec<Vec<f64>>,
386}
387
388#[derive(Debug, Clone)]
390pub struct ImagePreprocessor {
391 config: PreprocessingConfig,
393
394 norm_params: NormalizationParams,
396}
397
398#[derive(Debug, Clone)]
400pub struct NormalizationParams {
401 mean: Array1<f64>,
402 std: Array1<f64>,
403}
404
405#[derive(Debug, Clone)]
407pub struct VisionMetrics {
408 pub task_metrics: HashMap<String, f64>,
410
411 pub quantum_metrics: QuantumMetrics,
413
414 pub computational_metrics: ComputationalMetrics,
416}
417
418#[derive(Debug, Clone)]
420pub struct QuantumMetrics {
421 pub circuit_depth: usize,
423
424 pub entanglement_entropy: f64,
426
427 pub quantum_advantage: f64,
429
430 pub coherence_utilization: f64,
432}
433
434#[derive(Debug, Clone)]
436pub struct ComputationalMetrics {
437 pub flops: f64,
439
440 pub memory_mb: f64,
442
443 pub inference_ms: f64,
445
446 pub throughput: f64,
448}
449
450impl QuantumVisionConfig {
451 pub fn default() -> Self {
453 Self {
454 num_qubits: 12,
455 encoding_method: ImageEncodingMethod::AmplitudeEncoding,
456 backbone: VisionBackbone::QuantumCNN {
457 conv_layers: vec![
458 ConvolutionalConfig {
459 num_filters: 32,
460 kernel_size: 3,
461 stride: 1,
462 padding: 1,
463 quantum_kernel: true,
464 circuit_depth: 4,
465 },
466 ConvolutionalConfig {
467 num_filters: 64,
468 kernel_size: 3,
469 stride: 2,
470 padding: 1,
471 quantum_kernel: true,
472 circuit_depth: 6,
473 },
474 ],
475 pooling_type: PoolingType::Quantum,
476 },
477 task_config: VisionTaskConfig::Classification {
478 num_classes: 10,
479 multi_label: false,
480 },
481 preprocessing: PreprocessingConfig::default(),
482 quantum_enhancement: QuantumEnhancement::Medium,
483 }
484 }
485
486 pub fn object_detection(num_classes: usize) -> Self {
488 Self {
489 num_qubits: 16,
490 encoding_method: ImageEncodingMethod::NEQR { gray_levels: 256 },
491 backbone: VisionBackbone::HybridBackbone {
492 cnn_layers: 4,
493 transformer_layers: 2,
494 },
495 task_config: VisionTaskConfig::ObjectDetection {
496 num_classes,
497 anchor_sizes: vec![(32, 32), (64, 64), (128, 128)],
498 iou_threshold: 0.5,
499 },
500 preprocessing: PreprocessingConfig::detection_default(),
501 quantum_enhancement: QuantumEnhancement::High,
502 }
503 }
504
505 pub fn segmentation(num_classes: usize) -> Self {
507 Self {
508 num_qubits: 14,
509 encoding_method: ImageEncodingMethod::HierarchicalEncoding { levels: 3 },
510 backbone: VisionBackbone::QuantumViT {
511 patch_size: 16,
512 embed_dim: 768,
513 num_heads: 12,
514 depth: 12,
515 },
516 task_config: VisionTaskConfig::Segmentation {
517 num_classes,
518 output_stride: 8,
519 },
520 preprocessing: PreprocessingConfig::segmentation_default(),
521 quantum_enhancement: QuantumEnhancement::High,
522 }
523 }
524}
525
526impl PreprocessingConfig {
527 pub fn default() -> Self {
529 Self {
530 image_size: (224, 224),
531 normalize: true,
532 mean: vec![0.485, 0.456, 0.406],
533 std: vec![0.229, 0.224, 0.225],
534 augmentation: AugmentationConfig::default(),
535 color_space: ColorSpace::RGB,
536 }
537 }
538
539 pub fn detection_default() -> Self {
541 Self {
542 image_size: (416, 416),
543 normalize: true,
544 mean: vec![0.5, 0.5, 0.5],
545 std: vec![0.5, 0.5, 0.5],
546 augmentation: AugmentationConfig::detection(),
547 color_space: ColorSpace::RGB,
548 }
549 }
550
551 pub fn segmentation_default() -> Self {
553 Self {
554 image_size: (512, 512),
555 normalize: true,
556 mean: vec![0.485, 0.456, 0.406],
557 std: vec![0.229, 0.224, 0.225],
558 augmentation: AugmentationConfig::segmentation(),
559 color_space: ColorSpace::RGB,
560 }
561 }
562}
563
564impl AugmentationConfig {
565 pub fn default() -> Self {
567 Self {
568 horizontal_flip: true,
569 rotation_range: 15.0,
570 zoom_range: (0.8, 1.2),
571 brightness_range: (0.8, 1.2),
572 quantum_noise: false,
573 }
574 }
575
576 pub fn detection() -> Self {
578 Self {
579 horizontal_flip: true,
580 rotation_range: 5.0,
581 zoom_range: (0.9, 1.1),
582 brightness_range: (0.9, 1.1),
583 quantum_noise: true,
584 }
585 }
586
587 pub fn segmentation() -> Self {
589 Self {
590 horizontal_flip: true,
591 rotation_range: 10.0,
592 zoom_range: (0.85, 1.15),
593 brightness_range: (0.85, 1.15),
594 quantum_noise: false,
595 }
596 }
597}
598
599impl QuantumVisionPipeline {
600 pub fn new(config: QuantumVisionConfig) -> Result<Self> {
602 let encoder = QuantumImageEncoder::new(config.encoding_method.clone(), config.num_qubits)?;
604
605 let backbone: Box<dyn VisionModel> = match &config.backbone {
607 VisionBackbone::QuantumCNN {
608 conv_layers,
609 pooling_type,
610 } => Box::new(QuantumCNNBackbone::new(
611 conv_layers.clone(),
612 pooling_type.clone(),
613 config.num_qubits,
614 )?),
615 VisionBackbone::QuantumViT {
616 patch_size,
617 embed_dim,
618 num_heads,
619 depth,
620 } => Box::new(QuantumViTBackbone::new(
621 *patch_size,
622 *embed_dim,
623 *num_heads,
624 *depth,
625 config.num_qubits,
626 )?),
627 VisionBackbone::HybridBackbone {
628 cnn_layers,
629 transformer_layers,
630 } => Box::new(HybridVisionBackbone::new(
631 *cnn_layers,
632 *transformer_layers,
633 config.num_qubits,
634 )?),
635 VisionBackbone::QuantumResNet {
636 blocks,
637 skip_connections,
638 } => Box::new(QuantumResNetBackbone::new(
639 blocks.clone(),
640 *skip_connections,
641 config.num_qubits,
642 )?),
643 VisionBackbone::QuantumEfficientNet {
644 width_coefficient,
645 depth_coefficient,
646 } => Box::new(QuantumEfficientNetBackbone::new(
647 *width_coefficient,
648 *depth_coefficient,
649 config.num_qubits,
650 )?),
651 };
652
653 let task_head: Box<dyn TaskHead> = match &config.task_config {
655 VisionTaskConfig::Classification {
656 num_classes,
657 multi_label,
658 } => Box::new(ClassificationHead::new(*num_classes, *multi_label)?),
659 VisionTaskConfig::ObjectDetection {
660 num_classes,
661 anchor_sizes,
662 iou_threshold,
663 } => Box::new(DetectionHead::new(
664 *num_classes,
665 anchor_sizes.clone(),
666 *iou_threshold,
667 )?),
668 VisionTaskConfig::Segmentation {
669 num_classes,
670 output_stride,
671 } => Box::new(SegmentationHead::new(*num_classes, *output_stride)?),
672 VisionTaskConfig::InstanceSegmentation {
673 num_classes,
674 mask_resolution,
675 } => Box::new(InstanceSegmentationHead::new(
676 *num_classes,
677 *mask_resolution,
678 )?),
679 VisionTaskConfig::FeatureExtraction {
680 feature_dim,
681 normalize,
682 } => Box::new(FeatureExtractionHead::new(*feature_dim, *normalize)?),
683 VisionTaskConfig::Generation {
684 latent_dim,
685 output_channels,
686 } => Box::new(GenerationHead::new(*latent_dim, *output_channels)?),
687 };
688
689 let feature_extractor = QuantumFeatureExtractor::new(512, config.num_qubits)?;
691
692 let preprocessor = ImagePreprocessor::new(config.preprocessing.clone());
694
695 let metrics = VisionMetrics::new();
697
698 Ok(Self {
699 config,
700 encoder,
701 backbone,
702 task_head,
703 feature_extractor,
704 preprocessor,
705 metrics,
706 })
707 }
708
709 pub fn forward(&mut self, images: &Array4<f64>) -> Result<TaskOutput> {
711 let (batch_size, channels, height, width) = images.dim();
712
713 let processed = self.preprocessor.preprocess(images)?;
715
716 let encoded = self.encoder.encode(&processed)?;
718
719 let features = self.backbone.forward(&encoded)?;
721
722 let quantum_features = self.feature_extractor.extract(&features)?;
724
725 let output = self.task_head.forward(&quantum_features)?;
727
728 self.update_metrics(&features, &output);
730
731 Ok(output)
732 }
733
734 pub fn train(
736 &mut self,
737 train_data: &[(Array4<f64>, TaskTarget)],
738 val_data: &[(Array4<f64>, TaskTarget)],
739 epochs: usize,
740 optimizer: OptimizationMethod,
741 ) -> Result<TrainingHistory> {
742 let mut history = TrainingHistory::new();
743
744 for epoch in 0..epochs {
745 let mut train_loss = 0.0;
747
748 for (images, target) in train_data {
749 let output = self.forward(images)?;
750 let loss = self.compute_loss(&output, target)?;
751
752 self.backward(&loss)?;
754
755 self.update_parameters(&optimizer)?;
757
758 train_loss += loss;
759 }
760
761 let mut val_loss = 0.0;
763 let mut val_metrics = HashMap::new();
764
765 for (images, target) in val_data {
766 let output = self.forward(images)?;
767 let loss = self.compute_loss(&output, target)?;
768 val_loss += loss;
769
770 let metrics = self.evaluate_metrics(&output, target)?;
772 for (key, value) in metrics {
773 *val_metrics.entry(key).or_insert(0.0) += value;
774 }
775 }
776
777 train_loss /= train_data.len() as f64;
779 val_loss /= val_data.len() as f64;
780 for value in val_metrics.values_mut() {
781 *value /= val_data.len() as f64;
782 }
783
784 history.add_epoch(epoch, train_loss, val_loss, val_metrics);
786
787 println!(
788 "Epoch {}/{}: train_loss={:.4}, val_loss={:.4}",
789 epoch + 1,
790 epochs,
791 train_loss,
792 val_loss
793 );
794 }
795
796 Ok(history)
797 }
798
799 fn compute_loss(&self, output: &TaskOutput, target: &TaskTarget) -> Result<f64> {
801 match (output, target) {
802 (TaskOutput::Classification { logits, .. }, TaskTarget::Classification { labels }) => {
803 let mut loss = 0.0;
805 for (logit_row, &label) in logits.outer_iter().zip(labels.iter()) {
806 let max_logit = logit_row.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
807 let exp_logits: Vec<f64> =
808 logit_row.iter().map(|&x| (x - max_logit).exp()).collect();
809 let sum_exp: f64 = exp_logits.iter().sum();
810 let prob = exp_logits[label] / sum_exp;
811 loss -= prob.ln();
812 }
813 Ok(loss / labels.len() as f64)
814 }
815 _ => Ok(0.1), }
817 }
818
819 fn backward(&mut self, loss: &f64) -> Result<()> {
821 Ok(())
823 }
824
825 fn update_parameters(&mut self, optimizer: &OptimizationMethod) -> Result<()> {
827 Ok(())
829 }
830
831 fn evaluate_metrics(
833 &self,
834 output: &TaskOutput,
835 target: &TaskTarget,
836 ) -> Result<HashMap<String, f64>> {
837 let mut metrics = HashMap::new();
838
839 match (output, target) {
840 (
841 TaskOutput::Classification { probabilities, .. },
842 TaskTarget::Classification { labels },
843 ) => {
844 let mut correct = 0;
846 for (prob_row, &label) in probabilities.outer_iter().zip(labels.iter()) {
847 let predicted = prob_row
848 .iter()
849 .enumerate()
850 .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
851 .map(|(i, _)| i)
852 .unwrap_or(0);
853 if predicted == label {
854 correct += 1;
855 }
856 }
857 metrics.insert("accuracy".to_string(), correct as f64 / labels.len() as f64);
858 }
859 _ => {} }
861
862 Ok(metrics)
863 }
864
865 fn update_metrics(&mut self, features: &Array4<f64>, output: &TaskOutput) {
867 self.metrics.quantum_metrics.entanglement_entropy =
869 self.compute_entanglement_entropy(features);
870
871 self.metrics.computational_metrics.inference_ms = 10.0;
873 self.metrics.computational_metrics.throughput = 100.0;
874 }
875
876 fn compute_entanglement_entropy(&self, features: &Array4<f64>) -> f64 {
878 let variance = features.var(0.0);
880 variance.ln()
881 }
882
883 pub fn metrics(&self) -> &VisionMetrics {
885 &self.metrics
886 }
887}
888
889impl QuantumImageEncoder {
890 pub fn new(method: ImageEncodingMethod, num_qubits: usize) -> Result<Self> {
892 let encoding_circuits = match &method {
893 ImageEncodingMethod::AmplitudeEncoding => {
894 Self::create_amplitude_encoding_circuits(num_qubits)?
895 }
896 ImageEncodingMethod::AngleEncoding { basis } => {
897 Self::create_angle_encoding_circuits(num_qubits, basis)?
898 }
899 ImageEncodingMethod::FRQI => Self::create_frqi_circuits(num_qubits)?,
900 ImageEncodingMethod::NEQR { gray_levels } => {
901 Self::create_neqr_circuits(num_qubits, *gray_levels)?
902 }
903 ImageEncodingMethod::QPIE => Self::create_qpie_circuits(num_qubits)?,
904 ImageEncodingMethod::HierarchicalEncoding { levels } => {
905 Self::create_hierarchical_circuits(num_qubits, *levels)?
906 }
907 };
908
909 let parameters = Array1::zeros(encoding_circuits.len() * 10);
910
911 Ok(Self {
912 method,
913 num_qubits,
914 encoding_circuits,
915 parameters,
916 })
917 }
918
919 pub fn encode(&self, images: &Array4<f64>) -> Result<Array4<f64>> {
921 let (batch_size, channels, height, width) = images.dim();
922 let mut encoded = Array4::zeros((batch_size, channels, height, width));
923
924 for b in 0..batch_size {
926 for c in 0..channels {
927 let image_slice = images.slice(s![b, c, .., ..]).to_owned();
928 let encoded_slice = self.encode_single_channel(&image_slice)?;
929 encoded.slice_mut(s![b, c, .., ..]).assign(&encoded_slice);
930 }
931 }
932
933 Ok(encoded)
934 }
935
936 fn encode_single_channel(&self, channel: &Array2<f64>) -> Result<Array2<f64>> {
938 Ok(channel.mapv(|x| (x * PI).sin()))
940 }
941
942 fn create_amplitude_encoding_circuits(num_qubits: usize) -> Result<Vec<Circuit<16>>> {
944 let mut circuits = Vec::new();
945
946 let mut circuit = Circuit::<16>::new();
947
948 for i in 0..num_qubits.min(16) {
950 circuit.h(i);
951 }
952
953 for i in 0..num_qubits.min(16) {
955 circuit.ry(i, 0.0); }
957
958 circuits.push(circuit);
959
960 Ok(circuits)
961 }
962
963 fn create_angle_encoding_circuits(num_qubits: usize, basis: &str) -> Result<Vec<Circuit<16>>> {
965 let mut circuits = Vec::new();
966
967 let mut circuit = Circuit::<16>::new();
968
969 match basis {
970 "x" => {
971 for i in 0..num_qubits.min(16) {
972 circuit.rx(i, 0.0); }
974 }
975 "y" => {
976 for i in 0..num_qubits.min(16) {
977 circuit.ry(i, 0.0); }
979 }
980 "z" => {
981 for i in 0..num_qubits.min(16) {
982 circuit.rz(i, 0.0); }
984 }
985 _ => {
986 for i in 0..num_qubits.min(16) {
988 circuit.ry(i, 0.0); }
990 }
991 }
992
993 circuits.push(circuit);
994
995 Ok(circuits)
996 }
997
998 fn create_frqi_circuits(num_qubits: usize) -> Result<Vec<Circuit<16>>> {
1000 let mut circuits = Vec::new();
1001
1002 let mut circuit = Circuit::<16>::new();
1003
1004 let position_qubits = (num_qubits - 1).min(15);
1006 for i in 0..position_qubits {
1007 circuit.h(i);
1008 }
1009
1010 if position_qubits < 16 {
1012 circuit.ry(position_qubits, 0.0); }
1014
1015 circuits.push(circuit);
1016
1017 Ok(circuits)
1018 }
1019
1020 fn create_neqr_circuits(num_qubits: usize, gray_levels: usize) -> Result<Vec<Circuit<16>>> {
1022 let mut circuits = Vec::new();
1023
1024 let gray_qubits = (gray_levels as f64).log2().ceil() as usize;
1025 let position_qubits = num_qubits - gray_qubits;
1026
1027 let mut circuit = Circuit::<16>::new();
1028
1029 for i in 0..position_qubits.min(16) {
1031 circuit.h(i);
1032 }
1033
1034 for i in position_qubits..num_qubits.min(16) {
1036 circuit.ry(i, 0.0); }
1038
1039 circuits.push(circuit);
1040
1041 Ok(circuits)
1042 }
1043
1044 fn create_qpie_circuits(num_qubits: usize) -> Result<Vec<Circuit<16>>> {
1046 let mut circuits = Vec::new();
1047
1048 let mut circuit = Circuit::<16>::new();
1049
1050 for i in 0..num_qubits.min(16) {
1052 circuit.h(i);
1053 circuit.ry(i, 0.0); }
1055
1056 for i in 0..(num_qubits - 1).min(15) {
1058 circuit.cnot(i, i + 1);
1059 }
1060
1061 circuits.push(circuit);
1062
1063 Ok(circuits)
1064 }
1065
1066 fn create_hierarchical_circuits(num_qubits: usize, levels: usize) -> Result<Vec<Circuit<16>>> {
1068 let mut circuits = Vec::new();
1069
1070 let qubits_per_level = num_qubits / levels;
1071
1072 for level in 0..levels {
1073 let mut circuit = Circuit::<16>::new();
1074
1075 let start_qubit = level * qubits_per_level;
1076 let end_qubit = ((level + 1) * qubits_per_level).min(num_qubits).min(16);
1077
1078 for i in start_qubit..end_qubit {
1080 circuit.h(i);
1081 circuit.ry(i, 0.0); }
1083
1084 if level > 0 && start_qubit > 0 && start_qubit < 16 {
1086 circuit.cnot(start_qubit - 1, start_qubit);
1087 }
1088
1089 circuits.push(circuit);
1090 }
1091
1092 Ok(circuits)
1093 }
1094}
1095
1096#[derive(Debug, Clone)]
1098pub struct QuantumConvolutionalNN {
1099 num_filters: usize,
1101 kernel_size: usize,
1103 num_qubits: usize,
1105 parameters: Array1<f64>,
1107}
1108
1109impl QuantumConvolutionalNN {
1110 fn new(
1111 _layers: Vec<QNNLayerType>,
1112 num_qubits: usize,
1113 _input_size: usize,
1114 num_filters: usize,
1115 ) -> Result<Self> {
1116 Ok(Self {
1117 num_filters,
1118 kernel_size: 3,
1119 num_qubits,
1120 parameters: Array1::zeros(100),
1121 })
1122 }
1123}
1124
1125#[derive(Debug, Clone)]
1127struct QuantumCNNBackbone {
1128 conv_layers: Vec<QuantumConvolutionalNN>,
1130
1131 pooling_type: PoolingType,
1133
1134 num_qubits: usize,
1136
1137 parameters: Array1<f64>,
1139}
1140
1141impl QuantumCNNBackbone {
1142 fn new(
1143 conv_configs: Vec<ConvolutionalConfig>,
1144 pooling_type: PoolingType,
1145 num_qubits: usize,
1146 ) -> Result<Self> {
1147 let mut conv_layers = Vec::new();
1148
1149 for config in conv_configs {
1150 let qcnn = QuantumConvolutionalNN::new(
1151 vec![], num_qubits,
1153 224, config.num_filters,
1155 )?;
1156 conv_layers.push(qcnn);
1157 }
1158
1159 Ok(Self {
1160 conv_layers,
1161 pooling_type,
1162 num_qubits,
1163 parameters: Array1::zeros(100),
1164 })
1165 }
1166}
1167
1168impl VisionModel for QuantumCNNBackbone {
1169 fn forward(&self, input: &Array4<f64>) -> Result<Array4<f64>> {
1170 Ok(input.clone())
1172 }
1173
1174 fn parameters(&self) -> &Array1<f64> {
1175 &self.parameters
1176 }
1177
1178 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1179 Ok(())
1180 }
1181
1182 fn num_parameters(&self) -> usize {
1183 100
1184 }
1185
1186 fn clone_box(&self) -> Box<dyn VisionModel> {
1187 Box::new(self.clone())
1188 }
1189}
1190
1191#[derive(Debug, Clone)]
1193struct QuantumViTBackbone {
1194 patch_size: usize,
1196
1197 embed_dim: usize,
1199
1200 transformer: QuantumTransformer,
1202
1203 parameters: Array1<f64>,
1205}
1206
1207impl QuantumViTBackbone {
1208 fn new(
1209 patch_size: usize,
1210 embed_dim: usize,
1211 num_heads: usize,
1212 depth: usize,
1213 num_qubits: usize,
1214 ) -> Result<Self> {
1215 let config = QuantumTransformerConfig {
1216 model_dim: embed_dim,
1217 num_heads,
1218 ff_dim: embed_dim * 4,
1219 num_layers: depth,
1220 max_seq_len: 1024,
1221 num_qubits,
1222 dropout_rate: 0.1,
1223 attention_type: QuantumAttentionType::QuantumEnhancedMultiHead,
1224 position_encoding: crate::quantum_transformer::PositionEncodingType::LearnableQuantum,
1225 };
1226
1227 let transformer = QuantumTransformer::new(config)?;
1228
1229 Ok(Self {
1230 patch_size,
1231 embed_dim,
1232 transformer,
1233 parameters: Array1::zeros(1000),
1234 })
1235 }
1236}
1237
1238impl VisionModel for QuantumViTBackbone {
1239 fn forward(&self, input: &Array4<f64>) -> Result<Array4<f64>> {
1240 Ok(input.clone())
1242 }
1243
1244 fn parameters(&self) -> &Array1<f64> {
1245 &self.parameters
1246 }
1247
1248 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1249 Ok(())
1250 }
1251
1252 fn num_parameters(&self) -> usize {
1253 self.transformer.num_parameters()
1254 }
1255
1256 fn clone_box(&self) -> Box<dyn VisionModel> {
1257 Box::new(self.clone())
1258 }
1259}
1260
1261#[derive(Debug, Clone)]
1263struct HybridVisionBackbone {
1264 cnn_layers: usize,
1266
1267 transformer_layers: usize,
1269
1270 num_qubits: usize,
1272
1273 parameters: Array1<f64>,
1275}
1276
1277impl HybridVisionBackbone {
1278 fn new(cnn_layers: usize, transformer_layers: usize, num_qubits: usize) -> Result<Self> {
1279 Ok(Self {
1280 cnn_layers,
1281 transformer_layers,
1282 num_qubits,
1283 parameters: Array1::zeros(500),
1284 })
1285 }
1286}
1287
1288impl VisionModel for HybridVisionBackbone {
1289 fn forward(&self, input: &Array4<f64>) -> Result<Array4<f64>> {
1290 Ok(input.clone())
1291 }
1292
1293 fn parameters(&self) -> &Array1<f64> {
1294 &self.parameters
1295 }
1296
1297 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1298 Ok(())
1299 }
1300
1301 fn num_parameters(&self) -> usize {
1302 500
1303 }
1304
1305 fn clone_box(&self) -> Box<dyn VisionModel> {
1306 Box::new(self.clone())
1307 }
1308}
1309
1310#[derive(Debug, Clone)]
1312struct QuantumResNetBackbone {
1313 blocks: Vec<ResidualBlock>,
1315
1316 skip_connections: bool,
1318
1319 num_qubits: usize,
1321
1322 parameters: Array1<f64>,
1324}
1325
1326impl QuantumResNetBackbone {
1327 fn new(blocks: Vec<ResidualBlock>, skip_connections: bool, num_qubits: usize) -> Result<Self> {
1328 Ok(Self {
1329 blocks,
1330 skip_connections,
1331 num_qubits,
1332 parameters: Array1::zeros(1000),
1333 })
1334 }
1335}
1336
1337impl VisionModel for QuantumResNetBackbone {
1338 fn forward(&self, input: &Array4<f64>) -> Result<Array4<f64>> {
1339 Ok(input.clone())
1340 }
1341
1342 fn parameters(&self) -> &Array1<f64> {
1343 &self.parameters
1344 }
1345
1346 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1347 Ok(())
1348 }
1349
1350 fn num_parameters(&self) -> usize {
1351 1000
1352 }
1353
1354 fn clone_box(&self) -> Box<dyn VisionModel> {
1355 Box::new(self.clone())
1356 }
1357}
1358
1359#[derive(Debug, Clone)]
1361struct QuantumEfficientNetBackbone {
1362 width_coefficient: f64,
1364
1365 depth_coefficient: f64,
1367
1368 num_qubits: usize,
1370
1371 parameters: Array1<f64>,
1373}
1374
1375impl QuantumEfficientNetBackbone {
1376 fn new(width_coefficient: f64, depth_coefficient: f64, num_qubits: usize) -> Result<Self> {
1377 Ok(Self {
1378 width_coefficient,
1379 depth_coefficient,
1380 num_qubits,
1381 parameters: Array1::zeros(800),
1382 })
1383 }
1384}
1385
1386impl VisionModel for QuantumEfficientNetBackbone {
1387 fn forward(&self, input: &Array4<f64>) -> Result<Array4<f64>> {
1388 Ok(input.clone())
1389 }
1390
1391 fn parameters(&self) -> &Array1<f64> {
1392 &self.parameters
1393 }
1394
1395 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1396 Ok(())
1397 }
1398
1399 fn num_parameters(&self) -> usize {
1400 800
1401 }
1402
1403 fn clone_box(&self) -> Box<dyn VisionModel> {
1404 Box::new(self.clone())
1405 }
1406}
1407
1408#[derive(Debug, Clone)]
1410struct ClassificationHead {
1411 num_classes: usize,
1413
1414 multi_label: bool,
1416
1417 classifier: QuantumNeuralNetwork,
1419}
1420
1421impl ClassificationHead {
1422 fn new(num_classes: usize, multi_label: bool) -> Result<Self> {
1423 let layers = vec![
1424 QNNLayerType::EncodingLayer { num_features: 512 },
1425 QNNLayerType::VariationalLayer { num_params: 256 },
1426 QNNLayerType::VariationalLayer {
1427 num_params: num_classes,
1428 },
1429 QNNLayerType::MeasurementLayer {
1430 measurement_basis: "computational".to_string(),
1431 },
1432 ];
1433
1434 let classifier = QuantumNeuralNetwork::new(layers, 10, 512, num_classes)?;
1435
1436 Ok(Self {
1437 num_classes,
1438 multi_label,
1439 classifier,
1440 })
1441 }
1442}
1443
1444impl TaskHead for ClassificationHead {
1445 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput> {
1446 let (batch_size, _, _, _) = features.dim();
1447
1448 let pooled = features
1450 .mean_axis(Axis(2))
1451 .unwrap()
1452 .mean_axis(Axis(2))
1453 .unwrap();
1454
1455 let mut logits = Array2::zeros((batch_size, self.num_classes));
1457 let mut probabilities = Array2::zeros((batch_size, self.num_classes));
1458
1459 for i in 0..batch_size {
1460 let feature_vec = pooled.slice(s![i, ..]).to_owned();
1461 let class_logits = self.classifier.forward(&feature_vec)?;
1462
1463 let max_logit = class_logits
1465 .iter()
1466 .cloned()
1467 .fold(f64::NEG_INFINITY, f64::max);
1468 let exp_logits = class_logits.mapv(|x| (x - max_logit).exp());
1469 let sum_exp = exp_logits.sum();
1470 let probs = exp_logits / sum_exp;
1471
1472 logits.slice_mut(s![i, ..]).assign(&class_logits);
1473 probabilities.slice_mut(s![i, ..]).assign(&probs);
1474 }
1475
1476 Ok(TaskOutput::Classification {
1477 logits,
1478 probabilities,
1479 })
1480 }
1481
1482 fn parameters(&self) -> &Array1<f64> {
1483 &self.classifier.parameters
1484 }
1485
1486 fn update_parameters(&mut self, params: &Array1<f64>) -> Result<()> {
1487 self.classifier.parameters = params.clone();
1488 Ok(())
1489 }
1490
1491 fn clone_box(&self) -> Box<dyn TaskHead> {
1492 Box::new(self.clone())
1493 }
1494}
1495
1496#[derive(Debug, Clone)]
1498struct DetectionHead {
1499 num_classes: usize,
1500 anchor_sizes: Vec<(usize, usize)>,
1501 iou_threshold: f64,
1502 parameters: Array1<f64>,
1503}
1504
1505impl DetectionHead {
1506 fn new(
1507 num_classes: usize,
1508 anchor_sizes: Vec<(usize, usize)>,
1509 iou_threshold: f64,
1510 ) -> Result<Self> {
1511 Ok(Self {
1512 num_classes,
1513 anchor_sizes,
1514 iou_threshold,
1515 parameters: Array1::zeros(100),
1516 })
1517 }
1518}
1519
1520impl TaskHead for DetectionHead {
1521 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput> {
1522 let (batch_size, _, _, _) = features.dim();
1523
1524 let boxes = Array3::zeros((batch_size, 100, 4));
1526 let scores = Array2::zeros((batch_size, 100));
1527 let classes = Array2::<f64>::zeros((batch_size, 100));
1528
1529 Ok(TaskOutput::Detection {
1530 boxes,
1531 scores,
1532 classes: classes.mapv(|x| x as usize),
1533 })
1534 }
1535
1536 fn parameters(&self) -> &Array1<f64> {
1537 &self.parameters
1538 }
1539
1540 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1541 Ok(())
1542 }
1543
1544 fn clone_box(&self) -> Box<dyn TaskHead> {
1545 Box::new(self.clone())
1546 }
1547}
1548
1549#[derive(Debug, Clone)]
1550struct SegmentationHead {
1551 num_classes: usize,
1552 output_stride: usize,
1553 parameters: Array1<f64>,
1554}
1555
1556impl SegmentationHead {
1557 fn new(num_classes: usize, output_stride: usize) -> Result<Self> {
1558 Ok(Self {
1559 num_classes,
1560 output_stride,
1561 parameters: Array1::zeros(200),
1562 })
1563 }
1564}
1565
1566impl TaskHead for SegmentationHead {
1567 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput> {
1568 let (batch_size, _, height, width) = features.dim();
1569
1570 let masks = Array4::zeros((batch_size, self.num_classes, height, width));
1571 let class_scores = Array4::zeros((batch_size, self.num_classes, height, width));
1572
1573 Ok(TaskOutput::Segmentation {
1574 masks,
1575 class_scores,
1576 })
1577 }
1578
1579 fn parameters(&self) -> &Array1<f64> {
1580 &self.parameters
1581 }
1582
1583 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1584 Ok(())
1585 }
1586
1587 fn clone_box(&self) -> Box<dyn TaskHead> {
1588 Box::new(self.clone())
1589 }
1590}
1591
1592#[derive(Debug, Clone)]
1593struct InstanceSegmentationHead {
1594 num_classes: usize,
1595 mask_resolution: (usize, usize),
1596 parameters: Array1<f64>,
1597}
1598
1599impl InstanceSegmentationHead {
1600 fn new(num_classes: usize, mask_resolution: (usize, usize)) -> Result<Self> {
1601 Ok(Self {
1602 num_classes,
1603 mask_resolution,
1604 parameters: Array1::zeros(300),
1605 })
1606 }
1607}
1608
1609impl TaskHead for InstanceSegmentationHead {
1610 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput> {
1611 let (batch_size, _, _, _) = features.dim();
1612
1613 let masks = Array4::zeros((
1614 batch_size,
1615 self.num_classes,
1616 self.mask_resolution.0,
1617 self.mask_resolution.1,
1618 ));
1619 let class_scores = Array4::zeros((
1620 batch_size,
1621 self.num_classes,
1622 self.mask_resolution.0,
1623 self.mask_resolution.1,
1624 ));
1625
1626 Ok(TaskOutput::Segmentation {
1627 masks,
1628 class_scores,
1629 })
1630 }
1631
1632 fn parameters(&self) -> &Array1<f64> {
1633 &self.parameters
1634 }
1635
1636 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1637 Ok(())
1638 }
1639
1640 fn clone_box(&self) -> Box<dyn TaskHead> {
1641 Box::new(self.clone())
1642 }
1643}
1644
1645#[derive(Debug, Clone)]
1646struct FeatureExtractionHead {
1647 feature_dim: usize,
1648 normalize: bool,
1649 parameters: Array1<f64>,
1650}
1651
1652impl FeatureExtractionHead {
1653 fn new(feature_dim: usize, normalize: bool) -> Result<Self> {
1654 Ok(Self {
1655 feature_dim,
1656 normalize,
1657 parameters: Array1::zeros(50),
1658 })
1659 }
1660}
1661
1662impl TaskHead for FeatureExtractionHead {
1663 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput> {
1664 let (batch_size, channels, _, _) = features.dim();
1665
1666 let pooled = features
1668 .mean_axis(Axis(2))
1669 .unwrap()
1670 .mean_axis(Axis(2))
1671 .unwrap();
1672
1673 let mut extracted_features = Array2::zeros((batch_size, self.feature_dim));
1675
1676 for i in 0..batch_size {
1677 let feature_vec = pooled.slice(s![i, ..]).to_owned();
1678
1679 for j in 0..self.feature_dim {
1681 extracted_features[[i, j]] = feature_vec[j % channels];
1682 }
1683
1684 if self.normalize {
1686 let norm = extracted_features
1687 .slice(s![i, ..])
1688 .mapv(|x| x * x)
1689 .sum()
1690 .sqrt();
1691 if norm > 1e-10 {
1692 extracted_features
1693 .slice_mut(s![i, ..])
1694 .mapv_inplace(|x| x / norm);
1695 }
1696 }
1697 }
1698
1699 Ok(TaskOutput::Features {
1700 features: extracted_features,
1701 attention_maps: None,
1702 })
1703 }
1704
1705 fn parameters(&self) -> &Array1<f64> {
1706 &self.parameters
1707 }
1708
1709 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1710 Ok(())
1711 }
1712
1713 fn clone_box(&self) -> Box<dyn TaskHead> {
1714 Box::new(self.clone())
1715 }
1716}
1717
1718#[derive(Debug, Clone)]
1719struct GenerationHead {
1720 latent_dim: usize,
1721 output_channels: usize,
1722 parameters: Array1<f64>,
1723}
1724
1725impl GenerationHead {
1726 fn new(latent_dim: usize, output_channels: usize) -> Result<Self> {
1727 Ok(Self {
1728 latent_dim,
1729 output_channels,
1730 parameters: Array1::zeros(400),
1731 })
1732 }
1733}
1734
1735impl TaskHead for GenerationHead {
1736 fn forward(&self, features: &Array4<f64>) -> Result<TaskOutput> {
1737 let (batch_size, _, height, width) = features.dim();
1738
1739 let images = Array4::zeros((batch_size, self.output_channels, height, width));
1740 let latent_codes = Array2::zeros((batch_size, self.latent_dim));
1741
1742 Ok(TaskOutput::Generation {
1743 images,
1744 latent_codes,
1745 })
1746 }
1747
1748 fn parameters(&self) -> &Array1<f64> {
1749 &self.parameters
1750 }
1751
1752 fn update_parameters(&mut self, _params: &Array1<f64>) -> Result<()> {
1753 Ok(())
1754 }
1755
1756 fn clone_box(&self) -> Box<dyn TaskHead> {
1757 Box::new(self.clone())
1758 }
1759}
1760
1761impl QuantumFeatureExtractor {
1762 pub fn new(feature_dim: usize, num_qubits: usize) -> Result<Self> {
1764 let mut feature_circuit_params = Vec::new();
1766
1767 for _ in 0..5 {
1768 let mut params = Vec::new();
1769
1770 for _ in 0..num_qubits {
1771 params.push(1.0); params.push(0.0); }
1774
1775 for _ in 0..num_qubits - 1 {
1776 params.push(2.0); }
1778
1779 feature_circuit_params.push(params);
1780 }
1781
1782 let layers = vec![
1784 QNNLayerType::EncodingLayer { num_features: 256 },
1785 QNNLayerType::VariationalLayer {
1786 num_params: feature_dim,
1787 },
1788 QNNLayerType::MeasurementLayer {
1789 measurement_basis: "computational".to_string(),
1790 },
1791 ];
1792
1793 let transform_network = QuantumNeuralNetwork::new(layers, num_qubits, 256, feature_dim)?;
1794
1795 let attention = QuantumSpatialAttention::new(8, 64, num_qubits)?;
1797
1798 Ok(Self {
1799 feature_dim,
1800 feature_circuit_params,
1801 transform_network,
1802 attention,
1803 })
1804 }
1805
1806 pub fn extract(&self, features: &Array4<f64>) -> Result<Array4<f64>> {
1808 let attended = self.attention.apply(features)?;
1810
1811 Ok(attended)
1813 }
1814}
1815
1816impl QuantumSpatialAttention {
1817 pub fn new(num_heads: usize, attention_dim: usize, num_qubits: usize) -> Result<Self> {
1819 let mut attention_circuit_params = Vec::new();
1820
1821 for _ in 0..num_heads {
1822 let mut params = Vec::new();
1823
1824 for _ in 0..num_qubits.min(attention_dim / 8) {
1826 params.push(1.0); params.push(0.0); }
1829
1830 attention_circuit_params.push(params);
1831 }
1832
1833 Ok(Self {
1834 num_heads,
1835 attention_dim,
1836 attention_circuit_params,
1837 })
1838 }
1839
1840 pub fn apply(&self, features: &Array4<f64>) -> Result<Array4<f64>> {
1842 Ok(features.clone())
1844 }
1845}
1846
1847impl ImagePreprocessor {
1848 pub fn new(config: PreprocessingConfig) -> Self {
1850 let norm_params = NormalizationParams {
1851 mean: Array1::from_vec(config.mean.clone()),
1852 std: Array1::from_vec(config.std.clone()),
1853 };
1854
1855 Self {
1856 config,
1857 norm_params,
1858 }
1859 }
1860
1861 pub fn preprocess(&self, images: &Array4<f64>) -> Result<Array4<f64>> {
1863 let mut processed = images.clone();
1864
1865 if images.dim().2 != self.config.image_size.0 || images.dim().3 != self.config.image_size.1
1867 {
1868 processed = self.resize(&processed, self.config.image_size)?;
1869 }
1870
1871 if self.config.normalize {
1873 processed = self.normalize(&processed)?;
1874 }
1875
1876 if self.config.augmentation.horizontal_flip && fastrand::f64() > 0.5 {
1878 processed = self.horizontal_flip(&processed)?;
1879 }
1880
1881 Ok(processed)
1882 }
1883
1884 fn resize(&self, images: &Array4<f64>, size: (usize, usize)) -> Result<Array4<f64>> {
1886 let (batch_size, channels, _, _) = images.dim();
1887 let mut resized = Array4::zeros((batch_size, channels, size.0, size.1));
1888
1889 for b in 0..batch_size {
1891 for c in 0..channels {
1892 for h in 0..size.0 {
1893 for w in 0..size.1 {
1894 let src_h = h * images.dim().2 / size.0;
1895 let src_w = w * images.dim().3 / size.1;
1896 resized[[b, c, h, w]] = images[[b, c, src_h, src_w]];
1897 }
1898 }
1899 }
1900 }
1901
1902 Ok(resized)
1903 }
1904
1905 fn normalize(&self, images: &Array4<f64>) -> Result<Array4<f64>> {
1907 let mut normalized = images.clone();
1908 let channels = images.dim().1;
1909
1910 for c in 0..channels.min(self.norm_params.mean.len()) {
1911 let mean = self.norm_params.mean[c];
1912 let std = self.norm_params.std[c];
1913
1914 normalized
1915 .slice_mut(s![.., c, .., ..])
1916 .mapv_inplace(|x| (x - mean) / std);
1917 }
1918
1919 Ok(normalized)
1920 }
1921
1922 fn horizontal_flip(&self, images: &Array4<f64>) -> Result<Array4<f64>> {
1924 let (batch_size, channels, height, width) = images.dim();
1925 let mut flipped = Array4::zeros((batch_size, channels, height, width));
1926
1927 for b in 0..batch_size {
1928 for c in 0..channels {
1929 for h in 0..height {
1930 for w in 0..width {
1931 flipped[[b, c, h, w]] = images[[b, c, h, width - 1 - w]];
1932 }
1933 }
1934 }
1935 }
1936
1937 Ok(flipped)
1938 }
1939}
1940
1941impl VisionMetrics {
1942 pub fn new() -> Self {
1944 Self {
1945 task_metrics: HashMap::new(),
1946 quantum_metrics: QuantumMetrics {
1947 circuit_depth: 0,
1948 entanglement_entropy: 0.0,
1949 quantum_advantage: 1.0,
1950 coherence_utilization: 0.8,
1951 },
1952 computational_metrics: ComputationalMetrics {
1953 flops: 0.0,
1954 memory_mb: 0.0,
1955 inference_ms: 0.0,
1956 throughput: 0.0,
1957 },
1958 }
1959 }
1960}
1961
1962#[derive(Debug, Clone)]
1964pub enum TaskTarget {
1965 Classification {
1966 labels: Vec<usize>,
1967 },
1968 Detection {
1969 boxes: Array3<f64>,
1970 labels: Array2<usize>,
1971 },
1972 Segmentation {
1973 masks: Array4<usize>,
1974 },
1975 Features {
1976 target_features: Array2<f64>,
1977 },
1978}
1979
1980#[derive(Debug, Clone)]
1982pub struct TrainingHistory {
1983 pub epochs: Vec<usize>,
1984 pub train_losses: Vec<f64>,
1985 pub val_losses: Vec<f64>,
1986 pub metrics: Vec<HashMap<String, f64>>,
1987}
1988
1989impl TrainingHistory {
1990 fn new() -> Self {
1991 Self {
1992 epochs: Vec::new(),
1993 train_losses: Vec::new(),
1994 val_losses: Vec::new(),
1995 metrics: Vec::new(),
1996 }
1997 }
1998
1999 fn add_epoch(
2000 &mut self,
2001 epoch: usize,
2002 train_loss: f64,
2003 val_loss: f64,
2004 metrics: HashMap<String, f64>,
2005 ) {
2006 self.epochs.push(epoch);
2007 self.train_losses.push(train_loss);
2008 self.val_losses.push(val_loss);
2009 self.metrics.push(metrics);
2010 }
2011}
2012
2013#[cfg(test)]
2014mod tests {
2015 use super::*;
2016
2017 #[test]
2018 fn test_vision_config_creation() {
2019 let config = QuantumVisionConfig::default();
2020 assert_eq!(config.num_qubits, 12);
2021
2022 let detection_config = QuantumVisionConfig::object_detection(80);
2023 assert_eq!(detection_config.num_qubits, 16);
2024
2025 let seg_config = QuantumVisionConfig::segmentation(21);
2026 assert_eq!(seg_config.num_qubits, 14);
2027 }
2028
2029 #[test]
2030 fn test_image_encoder() {
2031 let encoder = QuantumImageEncoder::new(ImageEncodingMethod::AmplitudeEncoding, 8).unwrap();
2032
2033 assert_eq!(encoder.num_qubits, 8);
2034 assert!(!encoder.encoding_circuits.is_empty());
2035 }
2036
2037 #[test]
2038 fn test_preprocessing() {
2039 let config = PreprocessingConfig::default();
2040 let preprocessor = ImagePreprocessor::new(config);
2041
2042 let images = Array4::zeros((2, 3, 256, 256));
2043 let processed = preprocessor.preprocess(&images).unwrap();
2044
2045 assert_eq!(processed.dim(), (2, 3, 224, 224));
2046 }
2047}