1use super::{create_entangling_gates, EntanglementPattern, QMLLayer};
7use crate::{
8 error::{QuantRS2Error, QuantRS2Result},
9 gate::GateOp,
10 parametric::{ParametricRotationX, ParametricRotationY, ParametricRotationZ},
11 qubit::QubitId,
12};
13use scirs2_core::ndarray::Array1;
14use scirs2_core::Complex64;
15use std::f64::consts::PI;
16
17#[derive(Debug, Clone)]
19pub struct Parameter {
20 pub name: String,
21 pub value: f64,
22 pub bounds: Option<(f64, f64)>,
23}
24
25type RXGate = ParametricRotationX;
27type RYGate = ParametricRotationY;
28type RZGate = ParametricRotationZ;
29
30#[derive(Debug, Clone, Copy)]
32struct CNOT {
33 control: QubitId,
34 target: QubitId,
35}
36
37impl GateOp for CNOT {
38 fn name(&self) -> &'static str {
39 "CNOT"
40 }
41
42 fn qubits(&self) -> Vec<QubitId> {
43 vec![self.control, self.target]
44 }
45
46 fn matrix(&self) -> crate::error::QuantRS2Result<Vec<Complex64>> {
47 Ok(vec![
48 Complex64::new(1.0, 0.0),
49 Complex64::new(0.0, 0.0),
50 Complex64::new(0.0, 0.0),
51 Complex64::new(0.0, 0.0),
52 Complex64::new(0.0, 0.0),
53 Complex64::new(1.0, 0.0),
54 Complex64::new(0.0, 0.0),
55 Complex64::new(0.0, 0.0),
56 Complex64::new(0.0, 0.0),
57 Complex64::new(0.0, 0.0),
58 Complex64::new(0.0, 0.0),
59 Complex64::new(1.0, 0.0),
60 Complex64::new(0.0, 0.0),
61 Complex64::new(0.0, 0.0),
62 Complex64::new(1.0, 0.0),
63 Complex64::new(0.0, 0.0),
64 ])
65 }
66
67 fn as_any(&self) -> &dyn std::any::Any {
68 self
69 }
70
71 fn clone_gate(&self) -> Box<dyn GateOp> {
72 Box::new(*self)
73 }
74}
75
76#[derive(Debug, Clone)]
78pub struct RotationLayer {
79 num_qubits: usize,
81 axes: Vec<char>,
83 parameters: Vec<Parameter>,
85 name: String,
87}
88
89impl RotationLayer {
90 pub fn new(num_qubits: usize, axes: Vec<char>) -> QuantRS2Result<Self> {
92 if axes.len() != num_qubits {
93 return Err(QuantRS2Error::InvalidInput(format!(
94 "Expected {} axes, got {}",
95 num_qubits,
96 axes.len()
97 )));
98 }
99
100 for &axis in &axes {
101 if !['X', 'Y', 'Z'].contains(&axis) {
102 return Err(QuantRS2Error::InvalidInput(format!(
103 "Invalid rotation axis: {axis}"
104 )));
105 }
106 }
107
108 let parameters = (0..num_qubits)
109 .map(|i| Parameter {
110 name: format!("rot_{}_{}", axes[i], i),
111 value: 0.0,
112 bounds: Some((-2.0 * PI, 2.0 * PI)),
113 })
114 .collect();
115
116 let name = format!("RotationLayer_{}", axes.iter().collect::<String>());
117
118 Ok(Self {
119 num_qubits,
120 axes,
121 parameters,
122 name,
123 })
124 }
125
126 pub fn uniform(num_qubits: usize, axis: char) -> QuantRS2Result<Self> {
128 Self::new(num_qubits, vec![axis; num_qubits])
129 }
130}
131
132impl QMLLayer for RotationLayer {
133 fn num_qubits(&self) -> usize {
134 self.num_qubits
135 }
136
137 fn parameters(&self) -> &[Parameter] {
138 &self.parameters
139 }
140
141 fn parameters_mut(&mut self) -> &mut [Parameter] {
142 &mut self.parameters
143 }
144
145 fn gates(&self) -> Vec<Box<dyn GateOp>> {
146 self.parameters
147 .iter()
148 .enumerate()
149 .map(|(i, param)| {
150 let qubit = QubitId(i as u32);
151 let gate: Box<dyn GateOp> = match self.axes[i] {
152 'X' => Box::new(ParametricRotationX::new(qubit, param.value)),
153 'Y' => Box::new(ParametricRotationY::new(qubit, param.value)),
154 'Z' => Box::new(ParametricRotationZ::new(qubit, param.value)),
155 _ => unreachable!(),
156 };
157 gate
158 })
159 .collect()
160 }
161
162 fn compute_gradients(
163 &self,
164 state: &Array1<Complex64>,
165 loss_gradient: &Array1<Complex64>,
166 ) -> QuantRS2Result<Vec<f64>> {
167 let shift = std::f64::consts::PI / 2.0;
178 let mut gradients = Vec::with_capacity(self.parameters.len());
179
180 for (i, param) in self.parameters.iter().enumerate() {
181 let theta = param.value;
182 let qubit_idx = i;
190 if qubit_idx >= state.len() {
191 gradients.push(0.0);
192 continue;
193 }
194
195 let cos_shift = (theta + shift).cos() - (theta - shift).cos(); let sin_shift = (theta + shift).sin() - (theta - shift).sin(); let amp = state[qubit_idx];
204 let lg = loss_gradient[qubit_idx];
205 let d_amp = Complex64::new(
207 cos_shift / 2.0 * amp.re - sin_shift / 2.0 * amp.im,
208 cos_shift / 2.0 * amp.im + sin_shift / 2.0 * amp.re,
209 );
210 let grad = lg.re * d_amp.re + lg.im * d_amp.im;
211 gradients.push(grad);
212 }
213
214 Ok(gradients)
215 }
216
217 fn name(&self) -> &str {
218 &self.name
219 }
220}
221
222#[derive(Debug, Clone)]
224pub struct EntanglingLayer {
225 num_qubits: usize,
227 pattern: EntanglementPattern,
229 parameters: Vec<Parameter>,
231 parameterized: bool,
233 name: String,
235}
236
237impl EntanglingLayer {
238 pub fn new(num_qubits: usize, pattern: EntanglementPattern) -> Self {
240 let name = format!("EntanglingLayer_{pattern:?}");
241
242 Self {
243 num_qubits,
244 pattern,
245 parameters: vec![],
246 parameterized: false,
247 name,
248 }
249 }
250
251 pub fn parameterized(num_qubits: usize, pattern: EntanglementPattern) -> Self {
253 let pairs = create_entangling_gates(num_qubits, pattern);
254 let parameters = pairs
255 .iter()
256 .enumerate()
257 .map(|(_i, (ctrl, tgt))| Parameter {
258 name: format!("entangle_{}_{}", ctrl.0, tgt.0),
259 value: 0.0,
260 bounds: Some((-PI, PI)),
261 })
262 .collect();
263
264 let name = format!("ParameterizedEntanglingLayer_{pattern:?}");
265
266 Self {
267 num_qubits,
268 pattern,
269 parameters,
270 parameterized: true,
271 name,
272 }
273 }
274}
275
276impl QMLLayer for EntanglingLayer {
277 fn num_qubits(&self) -> usize {
278 self.num_qubits
279 }
280
281 fn parameters(&self) -> &[Parameter] {
282 &self.parameters
283 }
284
285 fn parameters_mut(&mut self) -> &mut [Parameter] {
286 &mut self.parameters
287 }
288
289 fn gates(&self) -> Vec<Box<dyn GateOp>> {
290 let pairs = create_entangling_gates(self.num_qubits, self.pattern);
291
292 if self.parameterized {
293 pairs
295 .iter()
296 .zip(self.parameters.iter())
297 .map(|((ctrl, tgt), _param)| {
298 Box::new(CNOT {
300 control: *ctrl,
301 target: *tgt,
302 }) as Box<dyn GateOp>
303 })
304 .collect()
305 } else {
306 pairs
308 .iter()
309 .map(|(ctrl, tgt)| {
310 Box::new(CNOT {
311 control: *ctrl,
312 target: *tgt,
313 }) as Box<dyn GateOp>
314 })
315 .collect()
316 }
317 }
318
319 fn compute_gradients(
320 &self,
321 _state: &Array1<Complex64>,
322 _loss_gradient: &Array1<Complex64>,
323 ) -> QuantRS2Result<Vec<f64>> {
324 if self.parameterized {
325 Ok(vec![0.0; self.parameters.len()])
327 } else {
328 Ok(vec![])
330 }
331 }
332
333 fn name(&self) -> &str {
334 &self.name
335 }
336}
337
338#[derive(Debug, Clone)]
340pub struct StronglyEntanglingLayer {
341 num_qubits: usize,
343 rotation_layers: Vec<RotationLayer>,
345 entangling_layer: EntanglingLayer,
347 total_parameters: usize,
349 name: String,
351}
352
353impl StronglyEntanglingLayer {
354 pub fn new(num_qubits: usize, pattern: EntanglementPattern) -> QuantRS2Result<Self> {
356 let rotation_layers = vec![
357 RotationLayer::uniform(num_qubits, 'X')?,
358 RotationLayer::uniform(num_qubits, 'Y')?,
359 RotationLayer::uniform(num_qubits, 'Z')?,
360 ];
361
362 let entangling_layer = EntanglingLayer::new(num_qubits, pattern);
363
364 let total_parameters = rotation_layers
365 .iter()
366 .map(|layer| layer.parameters().len())
367 .sum::<usize>()
368 + entangling_layer.parameters().len();
369
370 let name = format!("StronglyEntanglingLayer_{pattern:?}");
371
372 Ok(Self {
373 num_qubits,
374 rotation_layers,
375 entangling_layer,
376 total_parameters,
377 name,
378 })
379 }
380}
381
382impl QMLLayer for StronglyEntanglingLayer {
383 fn num_qubits(&self) -> usize {
384 self.num_qubits
385 }
386
387 fn parameters(&self) -> &[Parameter] {
388 &[]
391 }
392
393 fn parameters_mut(&mut self) -> &mut [Parameter] {
394 &mut []
396 }
397
398 fn set_parameters(&mut self, values: &[f64]) -> QuantRS2Result<()> {
399 if values.len() != self.total_parameters {
400 return Err(QuantRS2Error::InvalidInput(format!(
401 "Expected {} parameters, got {}",
402 self.total_parameters,
403 values.len()
404 )));
405 }
406
407 let mut offset = 0;
408 for layer in &mut self.rotation_layers {
409 let n = layer.parameters().len();
410 layer.set_parameters(&values[offset..offset + n])?;
411 offset += n;
412 }
413
414 if self.entangling_layer.parameterized {
415 self.entangling_layer.set_parameters(&values[offset..])?;
416 }
417
418 Ok(())
419 }
420
421 fn gates(&self) -> Vec<Box<dyn GateOp>> {
422 let mut gates = Vec::new();
423
424 for layer in &self.rotation_layers {
426 gates.extend(layer.gates());
427 }
428
429 gates.extend(self.entangling_layer.gates());
431
432 gates
433 }
434
435 fn compute_gradients(
436 &self,
437 state: &Array1<Complex64>,
438 loss_gradient: &Array1<Complex64>,
439 ) -> QuantRS2Result<Vec<f64>> {
440 let mut gradients = Vec::new();
441
442 for layer in &self.rotation_layers {
443 gradients.extend(layer.compute_gradients(state, loss_gradient)?);
444 }
445
446 if self.entangling_layer.parameterized {
447 gradients.extend(
448 self.entangling_layer
449 .compute_gradients(state, loss_gradient)?,
450 );
451 }
452
453 Ok(gradients)
454 }
455
456 fn name(&self) -> &str {
457 &self.name
458 }
459}
460
461#[derive(Debug, Clone)]
463pub struct HardwareEfficientLayer {
464 num_qubits: usize,
466 single_qubit_gates: Vec<RotationLayer>,
468 entangling_gates: EntanglingLayer,
470 name: String,
472}
473
474impl HardwareEfficientLayer {
475 pub fn new(num_qubits: usize) -> QuantRS2Result<Self> {
477 let single_qubit_gates = vec![
479 RotationLayer::uniform(num_qubits, 'Y')?,
480 RotationLayer::uniform(num_qubits, 'Z')?,
481 ];
482
483 let entangling_gates = EntanglingLayer::new(num_qubits, EntanglementPattern::Linear);
485
486 Ok(Self {
487 num_qubits,
488 single_qubit_gates,
489 entangling_gates,
490 name: "HardwareEfficientLayer".to_string(),
491 })
492 }
493}
494
495impl QMLLayer for HardwareEfficientLayer {
496 fn num_qubits(&self) -> usize {
497 self.num_qubits
498 }
499
500 fn parameters(&self) -> &[Parameter] {
501 &[]
503 }
504
505 fn parameters_mut(&mut self) -> &mut [Parameter] {
506 &mut []
507 }
508
509 fn gates(&self) -> Vec<Box<dyn GateOp>> {
510 let mut gates = Vec::new();
511
512 for layer in &self.single_qubit_gates {
513 gates.extend(layer.gates());
514 }
515
516 gates.extend(self.entangling_gates.gates());
517
518 gates
519 }
520
521 fn compute_gradients(
522 &self,
523 state: &Array1<Complex64>,
524 loss_gradient: &Array1<Complex64>,
525 ) -> QuantRS2Result<Vec<f64>> {
526 let mut gradients = Vec::new();
527
528 for layer in &self.single_qubit_gates {
529 gradients.extend(layer.compute_gradients(state, loss_gradient)?);
530 }
531
532 Ok(gradients)
533 }
534
535 fn name(&self) -> &str {
536 &self.name
537 }
538}
539
540#[derive(Debug, Clone)]
542pub struct QuantumPoolingLayer {
543 input_qubits: usize,
545 output_qubits: usize,
547 strategy: PoolingStrategy,
549 name: String,
551}
552
553#[derive(Debug, Clone, Copy)]
554pub enum PoolingStrategy {
555 TraceOut,
557 MeasureCondition,
559 Parameterized,
561}
562
563impl QuantumPoolingLayer {
564 pub fn new(input_qubits: usize, strategy: PoolingStrategy) -> Self {
566 let output_qubits = input_qubits / 2;
567
568 Self {
569 input_qubits,
570 output_qubits,
571 strategy,
572 name: format!("QuantumPoolingLayer_{strategy:?}"),
573 }
574 }
575}
576
577impl QMLLayer for QuantumPoolingLayer {
578 fn num_qubits(&self) -> usize {
579 self.input_qubits
580 }
581
582 fn parameters(&self) -> &[Parameter] {
583 &[]
584 }
585
586 fn parameters_mut(&mut self) -> &mut [Parameter] {
587 &mut []
588 }
589
590 fn gates(&self) -> Vec<Box<dyn GateOp>> {
591 vec![]
594 }
595
596 fn compute_gradients(
597 &self,
598 _state: &Array1<Complex64>,
599 _loss_gradient: &Array1<Complex64>,
600 ) -> QuantRS2Result<Vec<f64>> {
601 Ok(vec![])
602 }
603
604 fn name(&self) -> &str {
605 &self.name
606 }
607}
608
609#[cfg(test)]
610mod tests {
611 use super::*;
612
613 #[test]
614 fn test_rotation_layer() {
615 let layer = RotationLayer::uniform(3, 'X').expect("rotation layer creation should succeed");
616 assert_eq!(layer.num_qubits(), 3);
617 assert_eq!(layer.parameters().len(), 3);
618
619 let gates = layer.gates();
620 assert_eq!(gates.len(), 3);
621 }
622
623 #[test]
624 fn test_entangling_layer() {
625 let layer = EntanglingLayer::new(4, EntanglementPattern::Linear);
626 assert_eq!(layer.num_qubits(), 4);
627
628 let gates = layer.gates();
629 assert_eq!(gates.len(), 3); }
631
632 #[test]
633 fn test_strongly_entangling_layer() {
634 let layer = StronglyEntanglingLayer::new(2, EntanglementPattern::Full)
635 .expect("strongly entangling layer creation should succeed");
636 assert_eq!(layer.num_qubits(), 2);
637
638 let gates = layer.gates();
639 assert_eq!(gates.len(), 7); }
641
642 #[test]
643 fn test_hardware_efficient_layer() {
644 let layer = HardwareEfficientLayer::new(3)
645 .expect("hardware efficient layer creation should succeed");
646 assert_eq!(layer.num_qubits(), 3);
647
648 let gates = layer.gates();
649 assert_eq!(gates.len(), 8); }
651}