1use super::config::{AnsatzType, EntanglementPattern, QMLLayerConfig, RotationGate};
6use super::types::{
7 AttentionHead, ConvolutionalFilter, DenseConnection, LSTMGate, LSTMGateType, PQCGate,
8 PQCGateType, TwoQubitGate,
9};
10use crate::error::Result;
11use crate::statevector::StateVectorSimulator;
12use crate::SimulatorError;
13use scirs2_core::ndarray::Array1;
14use scirs2_core::random::prelude::*;
15use scirs2_core::Complex64;
16use std::f64::consts::PI;
17
18pub trait QMLLayer: std::fmt::Debug + Send + Sync {
20 fn forward(&mut self, input: &Array1<Complex64>) -> Result<Array1<Complex64>>;
22
23 fn backward(&mut self, gradient: &Array1<f64>) -> Result<Array1<f64>>;
25
26 fn get_parameters(&self) -> Array1<f64>;
28
29 fn set_parameters(&mut self, parameters: &Array1<f64>);
31
32 fn get_depth(&self) -> usize;
34
35 fn get_gate_count(&self) -> usize;
37
38 fn get_num_parameters(&self) -> usize;
40}
41
42#[derive(Debug)]
44pub struct ParameterizedQuantumCircuitLayer {
45 num_qubits: usize,
47 config: QMLLayerConfig,
49 parameters: Array1<f64>,
51 circuit_structure: Vec<PQCGate>,
53 simulator: StateVectorSimulator,
55}
56
57impl ParameterizedQuantumCircuitLayer {
58 pub fn new(num_qubits: usize, config: QMLLayerConfig) -> Result<Self> {
60 let mut layer = Self {
61 num_qubits,
62 config: config.clone(),
63 parameters: Array1::zeros(config.num_parameters),
64 circuit_structure: Vec::new(),
65 simulator: StateVectorSimulator::new(),
66 };
67
68 layer.initialize_parameters();
70
71 layer.build_circuit_structure()?;
73
74 Ok(layer)
75 }
76
77 fn initialize_parameters(&mut self) {
79 let mut rng = thread_rng();
80 for param in &mut self.parameters {
81 *param = rng.random_range(-PI..PI);
82 }
83 }
84
85 fn build_circuit_structure(&mut self) -> Result<()> {
87 match self.config.ansatz_type {
88 AnsatzType::Hardware => self.build_hardware_efficient_ansatz(),
89 AnsatzType::Layered => self.build_layered_ansatz(),
90 AnsatzType::BrickWall => self.build_brick_wall_ansatz(),
91 _ => Err(SimulatorError::InvalidConfiguration(
92 "Ansatz type not implemented".to_string(),
93 )),
94 }
95 }
96
97 fn build_hardware_efficient_ansatz(&mut self) -> Result<()> {
99 let mut param_idx = 0;
100
101 for _layer in 0..self.config.depth {
102 for qubit in 0..self.num_qubits {
104 for &gate_type in &self.config.rotation_gates {
105 if param_idx < self.parameters.len() {
106 self.circuit_structure.push(PQCGate {
107 gate_type: PQCGateType::SingleQubit(gate_type),
108 qubits: vec![qubit],
109 parameter_index: Some(param_idx),
110 });
111 param_idx += 1;
112 }
113 }
114 }
115
116 self.add_entangling_gates(¶m_idx);
118 }
119
120 Ok(())
121 }
122
123 fn build_layered_ansatz(&mut self) -> Result<()> {
125 self.build_hardware_efficient_ansatz()
127 }
128
129 fn build_brick_wall_ansatz(&mut self) -> Result<()> {
131 let mut param_idx = 0;
132
133 for layer in 0..self.config.depth {
134 let offset = layer % 2;
136 for i in (offset..self.num_qubits - 1).step_by(2) {
137 self.circuit_structure.push(PQCGate {
138 gate_type: PQCGateType::TwoQubit(TwoQubitGate::CNOT),
139 qubits: vec![i, i + 1],
140 parameter_index: None,
141 });
142 }
143
144 for qubit in 0..self.num_qubits {
146 if param_idx < self.parameters.len() {
147 self.circuit_structure.push(PQCGate {
148 gate_type: PQCGateType::SingleQubit(RotationGate::RY),
149 qubits: vec![qubit],
150 parameter_index: Some(param_idx),
151 });
152 param_idx += 1;
153 }
154 }
155 }
156
157 Ok(())
158 }
159
160 fn add_entangling_gates(&mut self, _param_idx: &usize) {
162 match self.config.entanglement_pattern {
163 EntanglementPattern::Linear => {
164 for i in 0..(self.num_qubits - 1) {
165 self.circuit_structure.push(PQCGate {
166 gate_type: PQCGateType::TwoQubit(TwoQubitGate::CNOT),
167 qubits: vec![i, i + 1],
168 parameter_index: None,
169 });
170 }
171 }
172 EntanglementPattern::Circular => {
173 for i in 0..self.num_qubits {
174 let next = (i + 1) % self.num_qubits;
175 self.circuit_structure.push(PQCGate {
176 gate_type: PQCGateType::TwoQubit(TwoQubitGate::CNOT),
177 qubits: vec![i, next],
178 parameter_index: None,
179 });
180 }
181 }
182 EntanglementPattern::AllToAll => {
183 for i in 0..self.num_qubits {
184 for j in (i + 1)..self.num_qubits {
185 self.circuit_structure.push(PQCGate {
186 gate_type: PQCGateType::TwoQubit(TwoQubitGate::CNOT),
187 qubits: vec![i, j],
188 parameter_index: None,
189 });
190 }
191 }
192 }
193 _ => {
194 for i in 0..(self.num_qubits - 1) {
196 self.circuit_structure.push(PQCGate {
197 gate_type: PQCGateType::TwoQubit(TwoQubitGate::CNOT),
198 qubits: vec![i, i + 1],
199 parameter_index: None,
200 });
201 }
202 }
203 }
204 }
205}
206
207impl QMLLayer for ParameterizedQuantumCircuitLayer {
208 fn forward(&mut self, input: &Array1<Complex64>) -> Result<Array1<Complex64>> {
209 let mut state = input.clone();
210
211 for gate in &self.circuit_structure {
213 state = self.apply_gate(&state, gate)?;
214 }
215
216 Ok(state)
217 }
218
219 fn backward(&mut self, gradient: &Array1<f64>) -> Result<Array1<f64>> {
220 Ok(gradient.clone())
222 }
223
224 fn get_parameters(&self) -> Array1<f64> {
225 self.parameters.clone()
226 }
227
228 fn set_parameters(&mut self, parameters: &Array1<f64>) {
229 self.parameters = parameters.clone();
230 }
231
232 fn get_depth(&self) -> usize {
233 self.config.depth
234 }
235
236 fn get_gate_count(&self) -> usize {
237 self.circuit_structure.len()
238 }
239
240 fn get_num_parameters(&self) -> usize {
241 self.parameters.len()
242 }
243}
244
245impl ParameterizedQuantumCircuitLayer {
246 fn apply_gate(&self, state: &Array1<Complex64>, gate: &PQCGate) -> Result<Array1<Complex64>> {
248 match &gate.gate_type {
249 PQCGateType::SingleQubit(rotation_gate) => {
250 let angle = if let Some(param_idx) = gate.parameter_index {
251 self.parameters[param_idx]
252 } else {
253 0.0
254 };
255 Self::apply_single_qubit_gate(state, gate.qubits[0], *rotation_gate, angle)
256 }
257 PQCGateType::TwoQubit(two_qubit_gate) => {
258 Self::apply_two_qubit_gate(state, gate.qubits[0], gate.qubits[1], *two_qubit_gate)
259 }
260 }
261 }
262
263 fn apply_single_qubit_gate(
265 state: &Array1<Complex64>,
266 qubit: usize,
267 gate_type: RotationGate,
268 angle: f64,
269 ) -> Result<Array1<Complex64>> {
270 let state_size = state.len();
271 let mut new_state = Array1::zeros(state_size);
272
273 match gate_type {
274 RotationGate::RX => {
275 let cos_half = (angle / 2.0).cos();
276 let sin_half = (angle / 2.0).sin();
277
278 for i in 0..state_size {
279 if i & (1 << qubit) == 0 {
280 let j = i | (1 << qubit);
281 if j < state_size {
282 new_state[i] = Complex64::new(cos_half, 0.0) * state[i]
283 + Complex64::new(0.0, -sin_half) * state[j];
284 new_state[j] = Complex64::new(0.0, -sin_half) * state[i]
285 + Complex64::new(cos_half, 0.0) * state[j];
286 }
287 }
288 }
289 }
290 RotationGate::RY => {
291 let cos_half = (angle / 2.0).cos();
292 let sin_half = (angle / 2.0).sin();
293
294 for i in 0..state_size {
295 if i & (1 << qubit) == 0 {
296 let j = i | (1 << qubit);
297 if j < state_size {
298 new_state[i] = Complex64::new(cos_half, 0.0) * state[i]
299 - Complex64::new(sin_half, 0.0) * state[j];
300 new_state[j] = Complex64::new(sin_half, 0.0) * state[i]
301 + Complex64::new(cos_half, 0.0) * state[j];
302 }
303 }
304 }
305 }
306 RotationGate::RZ => {
307 let phase_0 = Complex64::from_polar(1.0, -angle / 2.0);
308 let phase_1 = Complex64::from_polar(1.0, angle / 2.0);
309
310 for i in 0..state_size {
311 if i & (1 << qubit) == 0 {
312 new_state[i] = phase_0 * state[i];
313 } else {
314 new_state[i] = phase_1 * state[i];
315 }
316 }
317 }
318 _ => {
319 return Err(SimulatorError::InvalidGate(
320 "Gate type not implemented".to_string(),
321 ))
322 }
323 }
324
325 Ok(new_state)
326 }
327
328 fn apply_two_qubit_gate(
330 state: &Array1<Complex64>,
331 control: usize,
332 target: usize,
333 gate_type: TwoQubitGate,
334 ) -> Result<Array1<Complex64>> {
335 let state_size = state.len();
336 let mut new_state = state.clone();
337
338 match gate_type {
339 TwoQubitGate::CNOT => {
340 for i in 0..state_size {
341 if (i & (1 << control)) != 0 {
342 let j = i ^ (1 << target);
344 new_state[i] = state[j];
345 }
346 }
347 }
348 TwoQubitGate::CZ => {
349 for i in 0..state_size {
350 if (i & (1 << control)) != 0 && (i & (1 << target)) != 0 {
351 new_state[i] = -state[i];
353 }
354 }
355 }
356 TwoQubitGate::SWAP => {
357 for i in 0..state_size {
358 let ctrl_bit = (i & (1 << control)) != 0;
359 let targ_bit = (i & (1 << target)) != 0;
360 if ctrl_bit != targ_bit {
361 let j = i ^ (1 << control) ^ (1 << target);
363 new_state[i] = state[j];
364 }
365 }
366 }
367 TwoQubitGate::CPhase => {
368 for i in 0..state_size {
369 if (i & (1 << control)) != 0 && (i & (1 << target)) != 0 {
370 new_state[i] = -state[i];
372 }
373 }
374 }
375 }
376
377 Ok(new_state)
378 }
379}
380
381#[derive(Debug)]
383pub struct QuantumConvolutionalLayer {
384 num_qubits: usize,
386 config: QMLLayerConfig,
388 parameters: Array1<f64>,
390 conv_structure: Vec<ConvolutionalFilter>,
392}
393
394impl QuantumConvolutionalLayer {
395 pub fn new(num_qubits: usize, config: QMLLayerConfig) -> Result<Self> {
397 let mut layer = Self {
398 num_qubits,
399 config: config.clone(),
400 parameters: Array1::zeros(config.num_parameters),
401 conv_structure: Vec::new(),
402 };
403
404 layer.initialize_parameters();
405 layer.build_convolutional_structure()?;
406
407 Ok(layer)
408 }
409
410 fn initialize_parameters(&mut self) {
412 let mut rng = thread_rng();
413 for param in &mut self.parameters {
414 *param = rng.random_range(-PI..PI);
415 }
416 }
417
418 fn build_convolutional_structure(&mut self) -> Result<()> {
420 let filter_size = 2; let stride = 1;
423
424 let mut param_idx = 0;
425 for start in (0..=(self.num_qubits - filter_size)).step_by(stride) {
426 if param_idx + 2 <= self.parameters.len() {
427 self.conv_structure.push(ConvolutionalFilter {
428 qubits: vec![start, start + 1],
429 parameter_indices: vec![param_idx, param_idx + 1],
430 });
431 param_idx += 2;
432 }
433 }
434
435 Ok(())
436 }
437}
438
439impl QMLLayer for QuantumConvolutionalLayer {
440 fn forward(&mut self, input: &Array1<Complex64>) -> Result<Array1<Complex64>> {
441 let mut state = input.clone();
442
443 for filter in &self.conv_structure {
445 state = self.apply_convolutional_filter(&state, filter)?;
446 }
447
448 Ok(state)
449 }
450
451 fn backward(&mut self, gradient: &Array1<f64>) -> Result<Array1<f64>> {
452 Ok(gradient.clone())
453 }
454
455 fn get_parameters(&self) -> Array1<f64> {
456 self.parameters.clone()
457 }
458
459 fn set_parameters(&mut self, parameters: &Array1<f64>) {
460 self.parameters = parameters.clone();
461 }
462
463 fn get_depth(&self) -> usize {
464 self.conv_structure.len()
465 }
466
467 fn get_gate_count(&self) -> usize {
468 self.conv_structure.len() * 4 }
470
471 fn get_num_parameters(&self) -> usize {
472 self.parameters.len()
473 }
474}
475
476impl QuantumConvolutionalLayer {
477 fn apply_convolutional_filter(
479 &self,
480 state: &Array1<Complex64>,
481 filter: &ConvolutionalFilter,
482 ) -> Result<Array1<Complex64>> {
483 let mut new_state = state.clone();
484
485 let param1 = self.parameters[filter.parameter_indices[0]];
487 let param2 = self.parameters[filter.parameter_indices[1]];
488
489 new_state = Self::apply_ry_to_state(&new_state, filter.qubits[0], param1)?;
491 new_state = Self::apply_ry_to_state(&new_state, filter.qubits[1], param2)?;
492 new_state = Self::apply_cnot_to_state(&new_state, filter.qubits[0], filter.qubits[1])?;
493
494 Ok(new_state)
495 }
496
497 fn apply_ry_to_state(
499 state: &Array1<Complex64>,
500 qubit: usize,
501 angle: f64,
502 ) -> Result<Array1<Complex64>> {
503 let state_size = state.len();
504 let mut new_state = Array1::zeros(state_size);
505
506 let cos_half = (angle / 2.0).cos();
507 let sin_half = (angle / 2.0).sin();
508
509 for i in 0..state_size {
510 if i & (1 << qubit) == 0 {
511 let j = i | (1 << qubit);
512 if j < state_size {
513 new_state[i] = Complex64::new(cos_half, 0.0) * state[i]
514 - Complex64::new(sin_half, 0.0) * state[j];
515 new_state[j] = Complex64::new(sin_half, 0.0) * state[i]
516 + Complex64::new(cos_half, 0.0) * state[j];
517 }
518 }
519 }
520
521 Ok(new_state)
522 }
523
524 fn apply_cnot_to_state(
526 state: &Array1<Complex64>,
527 control: usize,
528 target: usize,
529 ) -> Result<Array1<Complex64>> {
530 let state_size = state.len();
531 let mut new_state = state.clone();
532
533 for i in 0..state_size {
534 if (i & (1 << control)) != 0 {
535 let j = i ^ (1 << target);
536 new_state[i] = state[j];
537 }
538 }
539
540 Ok(new_state)
541 }
542}
543
544#[derive(Debug)]
546pub struct QuantumDenseLayer {
547 num_qubits: usize,
549 config: QMLLayerConfig,
551 parameters: Array1<f64>,
553 dense_structure: Vec<DenseConnection>,
555}
556
557impl QuantumDenseLayer {
558 pub fn new(num_qubits: usize, config: QMLLayerConfig) -> Result<Self> {
560 let mut layer = Self {
561 num_qubits,
562 config: config.clone(),
563 parameters: Array1::zeros(config.num_parameters),
564 dense_structure: Vec::new(),
565 };
566
567 layer.initialize_parameters();
568 layer.build_dense_structure()?;
569
570 Ok(layer)
571 }
572
573 fn initialize_parameters(&mut self) {
575 let mut rng = thread_rng();
576 for param in &mut self.parameters {
577 *param = rng.random_range(-PI..PI);
578 }
579 }
580
581 fn build_dense_structure(&mut self) -> Result<()> {
583 let mut param_idx = 0;
584
585 for i in 0..self.num_qubits {
587 for j in (i + 1)..self.num_qubits {
588 if param_idx < self.parameters.len() {
589 self.dense_structure.push(DenseConnection {
590 qubit1: i,
591 qubit2: j,
592 parameter_index: param_idx,
593 });
594 param_idx += 1;
595 }
596 }
597 }
598
599 Ok(())
600 }
601}
602
603impl QMLLayer for QuantumDenseLayer {
604 fn forward(&mut self, input: &Array1<Complex64>) -> Result<Array1<Complex64>> {
605 let mut state = input.clone();
606
607 for connection in &self.dense_structure {
609 state = self.apply_dense_connection(&state, connection)?;
610 }
611
612 Ok(state)
613 }
614
615 fn backward(&mut self, gradient: &Array1<f64>) -> Result<Array1<f64>> {
616 Ok(gradient.clone())
617 }
618
619 fn get_parameters(&self) -> Array1<f64> {
620 self.parameters.clone()
621 }
622
623 fn set_parameters(&mut self, parameters: &Array1<f64>) {
624 self.parameters = parameters.clone();
625 }
626
627 fn get_depth(&self) -> usize {
628 1 }
630
631 fn get_gate_count(&self) -> usize {
632 self.dense_structure.len() * 2 }
634
635 fn get_num_parameters(&self) -> usize {
636 self.parameters.len()
637 }
638}
639
640impl QuantumDenseLayer {
641 fn apply_dense_connection(
643 &self,
644 state: &Array1<Complex64>,
645 connection: &DenseConnection,
646 ) -> Result<Array1<Complex64>> {
647 let angle = self.parameters[connection.parameter_index];
648
649 Self::apply_parameterized_two_qubit_gate(state, connection.qubit1, connection.qubit2, angle)
651 }
652
653 fn apply_parameterized_two_qubit_gate(
655 state: &Array1<Complex64>,
656 qubit1: usize,
657 qubit2: usize,
658 angle: f64,
659 ) -> Result<Array1<Complex64>> {
660 let state_size = state.len();
661 let mut new_state = state.clone();
662
663 let cos_val = angle.cos();
665 let sin_val = angle.sin();
666
667 for i in 0..state_size {
668 if (i & (1 << qubit1)) != 0 && (i & (1 << qubit2)) != 0 {
669 let phase = Complex64::new(cos_val, sin_val);
671 new_state[i] *= phase;
672 }
673 }
674
675 Ok(new_state)
676 }
677}
678
679#[derive(Debug)]
681pub struct QuantumLSTMLayer {
682 num_qubits: usize,
684 config: QMLLayerConfig,
686 parameters: Array1<f64>,
688 lstm_gates: Vec<LSTMGate>,
690 hidden_state: Option<Array1<Complex64>>,
692 cell_state: Option<Array1<Complex64>>,
694}
695
696impl QuantumLSTMLayer {
697 pub fn new(num_qubits: usize, config: QMLLayerConfig) -> Result<Self> {
699 let mut layer = Self {
700 num_qubits,
701 config: config.clone(),
702 parameters: Array1::zeros(config.num_parameters),
703 lstm_gates: Vec::new(),
704 hidden_state: None,
705 cell_state: None,
706 };
707
708 layer.initialize_parameters();
709 layer.build_lstm_structure()?;
710
711 Ok(layer)
712 }
713
714 fn initialize_parameters(&mut self) {
716 let mut rng = thread_rng();
717 for param in &mut self.parameters {
718 *param = rng.random_range(-PI..PI);
719 }
720 }
721
722 fn build_lstm_structure(&mut self) -> Result<()> {
724 let params_per_gate = self.parameters.len() / 4; self.lstm_gates = vec![
727 LSTMGate {
728 gate_type: LSTMGateType::Forget,
729 parameter_start: 0,
730 parameter_count: params_per_gate,
731 },
732 LSTMGate {
733 gate_type: LSTMGateType::Input,
734 parameter_start: params_per_gate,
735 parameter_count: params_per_gate,
736 },
737 LSTMGate {
738 gate_type: LSTMGateType::Output,
739 parameter_start: 2 * params_per_gate,
740 parameter_count: params_per_gate,
741 },
742 LSTMGate {
743 gate_type: LSTMGateType::Candidate,
744 parameter_start: 3 * params_per_gate,
745 parameter_count: params_per_gate,
746 },
747 ];
748
749 Ok(())
750 }
751}
752
753impl QMLLayer for QuantumLSTMLayer {
754 fn forward(&mut self, input: &Array1<Complex64>) -> Result<Array1<Complex64>> {
755 if self.hidden_state.is_none() {
757 let state_size = 1 << self.num_qubits;
758 let mut hidden = Array1::zeros(state_size);
759 let mut cell = Array1::zeros(state_size);
760 hidden[0] = Complex64::new(1.0, 0.0);
762 cell[0] = Complex64::new(1.0, 0.0);
763 self.hidden_state = Some(hidden);
764 self.cell_state = Some(cell);
765 }
766
767 let mut current_state = input.clone();
768
769 for gate in &self.lstm_gates {
771 current_state = self.apply_lstm_gate(¤t_state, gate)?;
772 }
773
774 self.hidden_state = Some(current_state.clone());
776
777 Ok(current_state)
778 }
779
780 fn backward(&mut self, gradient: &Array1<f64>) -> Result<Array1<f64>> {
781 Ok(gradient.clone())
782 }
783
784 fn get_parameters(&self) -> Array1<f64> {
785 self.parameters.clone()
786 }
787
788 fn set_parameters(&mut self, parameters: &Array1<f64>) {
789 self.parameters = parameters.clone();
790 }
791
792 fn get_depth(&self) -> usize {
793 self.lstm_gates.len()
794 }
795
796 fn get_gate_count(&self) -> usize {
797 self.parameters.len() }
799
800 fn get_num_parameters(&self) -> usize {
801 self.parameters.len()
802 }
803}
804
805impl QuantumLSTMLayer {
806 fn apply_lstm_gate(
808 &self,
809 state: &Array1<Complex64>,
810 gate: &LSTMGate,
811 ) -> Result<Array1<Complex64>> {
812 let mut new_state = state.clone();
813
814 for i in 0..gate.parameter_count {
816 let param_idx = gate.parameter_start + i;
817 if param_idx < self.parameters.len() {
818 let angle = self.parameters[param_idx];
819 let qubit = i % self.num_qubits;
820
821 new_state = Self::apply_rotation(&new_state, qubit, angle)?;
823 }
824 }
825
826 Ok(new_state)
827 }
828
829 fn apply_rotation(
831 state: &Array1<Complex64>,
832 qubit: usize,
833 angle: f64,
834 ) -> Result<Array1<Complex64>> {
835 let state_size = state.len();
836 let mut new_state = Array1::zeros(state_size);
837
838 let cos_half = (angle / 2.0).cos();
839 let sin_half = (angle / 2.0).sin();
840
841 for i in 0..state_size {
842 if i & (1 << qubit) == 0 {
843 let j = i | (1 << qubit);
844 if j < state_size {
845 new_state[i] = Complex64::new(cos_half, 0.0) * state[i]
846 - Complex64::new(sin_half, 0.0) * state[j];
847 new_state[j] = Complex64::new(sin_half, 0.0) * state[i]
848 + Complex64::new(cos_half, 0.0) * state[j];
849 }
850 }
851 }
852
853 Ok(new_state)
854 }
855
856 #[must_use]
858 pub fn get_lstm_gates(&self) -> &[LSTMGate] {
859 &self.lstm_gates
860 }
861}
862
863#[derive(Debug)]
865pub struct QuantumAttentionLayer {
866 num_qubits: usize,
868 config: QMLLayerConfig,
870 parameters: Array1<f64>,
872 attention_structure: Vec<AttentionHead>,
874}
875
876impl QuantumAttentionLayer {
877 pub fn new(num_qubits: usize, config: QMLLayerConfig) -> Result<Self> {
879 let mut layer = Self {
880 num_qubits,
881 config: config.clone(),
882 parameters: Array1::zeros(config.num_parameters),
883 attention_structure: Vec::new(),
884 };
885
886 layer.initialize_parameters();
887 layer.build_attention_structure()?;
888
889 Ok(layer)
890 }
891
892 fn initialize_parameters(&mut self) {
894 let mut rng = thread_rng();
895 for param in &mut self.parameters {
896 *param = rng.random_range(-PI..PI);
897 }
898 }
899
900 fn build_attention_structure(&mut self) -> Result<()> {
902 let num_heads = 2; let params_per_head = self.parameters.len() / num_heads;
904
905 for head in 0..num_heads {
906 self.attention_structure.push(AttentionHead {
907 head_id: head,
908 parameter_start: head * params_per_head,
909 parameter_count: params_per_head,
910 query_qubits: (0..self.num_qubits / 2).collect(),
911 key_qubits: (self.num_qubits / 2..self.num_qubits).collect(),
912 });
913 }
914
915 Ok(())
916 }
917}
918
919impl QMLLayer for QuantumAttentionLayer {
920 fn forward(&mut self, input: &Array1<Complex64>) -> Result<Array1<Complex64>> {
921 let mut state = input.clone();
922
923 for head in &self.attention_structure {
925 state = self.apply_attention_head(&state, head)?;
926 }
927
928 Ok(state)
929 }
930
931 fn backward(&mut self, gradient: &Array1<f64>) -> Result<Array1<f64>> {
932 Ok(gradient.clone())
933 }
934
935 fn get_parameters(&self) -> Array1<f64> {
936 self.parameters.clone()
937 }
938
939 fn set_parameters(&mut self, parameters: &Array1<f64>) {
940 self.parameters = parameters.clone();
941 }
942
943 fn get_depth(&self) -> usize {
944 self.attention_structure.len()
945 }
946
947 fn get_gate_count(&self) -> usize {
948 self.parameters.len()
949 }
950
951 fn get_num_parameters(&self) -> usize {
952 self.parameters.len()
953 }
954}
955
956impl QuantumAttentionLayer {
957 fn apply_attention_head(
959 &self,
960 state: &Array1<Complex64>,
961 head: &AttentionHead,
962 ) -> Result<Array1<Complex64>> {
963 let mut new_state = state.clone();
964
965 for i in 0..head.parameter_count {
967 let param_idx = head.parameter_start + i;
968 if param_idx < self.parameters.len() {
969 let angle = self.parameters[param_idx];
970
971 if i < head.query_qubits.len() && i < head.key_qubits.len() {
973 let query_qubit = head.query_qubits[i];
974 let key_qubit = head.key_qubits[i];
975
976 new_state =
977 Self::apply_attention_gate(&new_state, query_qubit, key_qubit, angle)?;
978 }
979 }
980 }
981
982 Ok(new_state)
983 }
984
985 fn apply_attention_gate(
987 state: &Array1<Complex64>,
988 query_qubit: usize,
989 key_qubit: usize,
990 angle: f64,
991 ) -> Result<Array1<Complex64>> {
992 let state_size = state.len();
993 let mut new_state = state.clone();
994
995 let cos_val = angle.cos();
997 let sin_val = angle.sin();
998
999 for i in 0..state_size {
1000 if (i & (1 << query_qubit)) != 0 {
1001 let key_state = (i & (1 << key_qubit)) != 0;
1003 let attention_phase = if key_state {
1004 Complex64::new(cos_val, sin_val)
1005 } else {
1006 Complex64::new(cos_val, -sin_val)
1007 };
1008 new_state[i] *= attention_phase;
1009 }
1010 }
1011
1012 Ok(new_state)
1013 }
1014
1015 #[must_use]
1017 pub fn get_attention_structure(&self) -> &[AttentionHead] {
1018 &self.attention_structure
1019 }
1020}