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 gradients = vec![0.0; self.parameters.len()];
170 Ok(gradients)
171 }
172
173 fn name(&self) -> &str {
174 &self.name
175 }
176}
177
178#[derive(Debug, Clone)]
180pub struct EntanglingLayer {
181 num_qubits: usize,
183 pattern: EntanglementPattern,
185 parameters: Vec<Parameter>,
187 parameterized: bool,
189 name: String,
191}
192
193impl EntanglingLayer {
194 pub fn new(num_qubits: usize, pattern: EntanglementPattern) -> Self {
196 let name = format!("EntanglingLayer_{pattern:?}");
197
198 Self {
199 num_qubits,
200 pattern,
201 parameters: vec![],
202 parameterized: false,
203 name,
204 }
205 }
206
207 pub fn parameterized(num_qubits: usize, pattern: EntanglementPattern) -> Self {
209 let pairs = create_entangling_gates(num_qubits, pattern);
210 let parameters = pairs
211 .iter()
212 .enumerate()
213 .map(|(_i, (ctrl, tgt))| Parameter {
214 name: format!("entangle_{}_{}", ctrl.0, tgt.0),
215 value: 0.0,
216 bounds: Some((-PI, PI)),
217 })
218 .collect();
219
220 let name = format!("ParameterizedEntanglingLayer_{pattern:?}");
221
222 Self {
223 num_qubits,
224 pattern,
225 parameters,
226 parameterized: true,
227 name,
228 }
229 }
230}
231
232impl QMLLayer for EntanglingLayer {
233 fn num_qubits(&self) -> usize {
234 self.num_qubits
235 }
236
237 fn parameters(&self) -> &[Parameter] {
238 &self.parameters
239 }
240
241 fn parameters_mut(&mut self) -> &mut [Parameter] {
242 &mut self.parameters
243 }
244
245 fn gates(&self) -> Vec<Box<dyn GateOp>> {
246 let pairs = create_entangling_gates(self.num_qubits, self.pattern);
247
248 if self.parameterized {
249 pairs
251 .iter()
252 .zip(self.parameters.iter())
253 .map(|((ctrl, tgt), _param)| {
254 Box::new(CNOT {
256 control: *ctrl,
257 target: *tgt,
258 }) as Box<dyn GateOp>
259 })
260 .collect()
261 } else {
262 pairs
264 .iter()
265 .map(|(ctrl, tgt)| {
266 Box::new(CNOT {
267 control: *ctrl,
268 target: *tgt,
269 }) as Box<dyn GateOp>
270 })
271 .collect()
272 }
273 }
274
275 fn compute_gradients(
276 &self,
277 _state: &Array1<Complex64>,
278 _loss_gradient: &Array1<Complex64>,
279 ) -> QuantRS2Result<Vec<f64>> {
280 if self.parameterized {
281 Ok(vec![0.0; self.parameters.len()])
283 } else {
284 Ok(vec![])
286 }
287 }
288
289 fn name(&self) -> &str {
290 &self.name
291 }
292}
293
294#[derive(Debug, Clone)]
296pub struct StronglyEntanglingLayer {
297 num_qubits: usize,
299 rotation_layers: Vec<RotationLayer>,
301 entangling_layer: EntanglingLayer,
303 total_parameters: usize,
305 name: String,
307}
308
309impl StronglyEntanglingLayer {
310 pub fn new(num_qubits: usize, pattern: EntanglementPattern) -> QuantRS2Result<Self> {
312 let rotation_layers = vec![
313 RotationLayer::uniform(num_qubits, 'X')?,
314 RotationLayer::uniform(num_qubits, 'Y')?,
315 RotationLayer::uniform(num_qubits, 'Z')?,
316 ];
317
318 let entangling_layer = EntanglingLayer::new(num_qubits, pattern);
319
320 let total_parameters = rotation_layers
321 .iter()
322 .map(|layer| layer.parameters().len())
323 .sum::<usize>()
324 + entangling_layer.parameters().len();
325
326 let name = format!("StronglyEntanglingLayer_{pattern:?}");
327
328 Ok(Self {
329 num_qubits,
330 rotation_layers,
331 entangling_layer,
332 total_parameters,
333 name,
334 })
335 }
336}
337
338impl QMLLayer for StronglyEntanglingLayer {
339 fn num_qubits(&self) -> usize {
340 self.num_qubits
341 }
342
343 fn parameters(&self) -> &[Parameter] {
344 &[]
347 }
348
349 fn parameters_mut(&mut self) -> &mut [Parameter] {
350 &mut []
352 }
353
354 fn set_parameters(&mut self, values: &[f64]) -> QuantRS2Result<()> {
355 if values.len() != self.total_parameters {
356 return Err(QuantRS2Error::InvalidInput(format!(
357 "Expected {} parameters, got {}",
358 self.total_parameters,
359 values.len()
360 )));
361 }
362
363 let mut offset = 0;
364 for layer in &mut self.rotation_layers {
365 let n = layer.parameters().len();
366 layer.set_parameters(&values[offset..offset + n])?;
367 offset += n;
368 }
369
370 if self.entangling_layer.parameterized {
371 self.entangling_layer.set_parameters(&values[offset..])?;
372 }
373
374 Ok(())
375 }
376
377 fn gates(&self) -> Vec<Box<dyn GateOp>> {
378 let mut gates = Vec::new();
379
380 for layer in &self.rotation_layers {
382 gates.extend(layer.gates());
383 }
384
385 gates.extend(self.entangling_layer.gates());
387
388 gates
389 }
390
391 fn compute_gradients(
392 &self,
393 state: &Array1<Complex64>,
394 loss_gradient: &Array1<Complex64>,
395 ) -> QuantRS2Result<Vec<f64>> {
396 let mut gradients = Vec::new();
397
398 for layer in &self.rotation_layers {
399 gradients.extend(layer.compute_gradients(state, loss_gradient)?);
400 }
401
402 if self.entangling_layer.parameterized {
403 gradients.extend(
404 self.entangling_layer
405 .compute_gradients(state, loss_gradient)?,
406 );
407 }
408
409 Ok(gradients)
410 }
411
412 fn name(&self) -> &str {
413 &self.name
414 }
415}
416
417#[derive(Debug, Clone)]
419pub struct HardwareEfficientLayer {
420 num_qubits: usize,
422 single_qubit_gates: Vec<RotationLayer>,
424 entangling_gates: EntanglingLayer,
426 name: String,
428}
429
430impl HardwareEfficientLayer {
431 pub fn new(num_qubits: usize) -> QuantRS2Result<Self> {
433 let single_qubit_gates = vec![
435 RotationLayer::uniform(num_qubits, 'Y')?,
436 RotationLayer::uniform(num_qubits, 'Z')?,
437 ];
438
439 let entangling_gates = EntanglingLayer::new(num_qubits, EntanglementPattern::Linear);
441
442 Ok(Self {
443 num_qubits,
444 single_qubit_gates,
445 entangling_gates,
446 name: "HardwareEfficientLayer".to_string(),
447 })
448 }
449}
450
451impl QMLLayer for HardwareEfficientLayer {
452 fn num_qubits(&self) -> usize {
453 self.num_qubits
454 }
455
456 fn parameters(&self) -> &[Parameter] {
457 &[]
459 }
460
461 fn parameters_mut(&mut self) -> &mut [Parameter] {
462 &mut []
463 }
464
465 fn gates(&self) -> Vec<Box<dyn GateOp>> {
466 let mut gates = Vec::new();
467
468 for layer in &self.single_qubit_gates {
469 gates.extend(layer.gates());
470 }
471
472 gates.extend(self.entangling_gates.gates());
473
474 gates
475 }
476
477 fn compute_gradients(
478 &self,
479 state: &Array1<Complex64>,
480 loss_gradient: &Array1<Complex64>,
481 ) -> QuantRS2Result<Vec<f64>> {
482 let mut gradients = Vec::new();
483
484 for layer in &self.single_qubit_gates {
485 gradients.extend(layer.compute_gradients(state, loss_gradient)?);
486 }
487
488 Ok(gradients)
489 }
490
491 fn name(&self) -> &str {
492 &self.name
493 }
494}
495
496#[derive(Debug, Clone)]
498pub struct QuantumPoolingLayer {
499 input_qubits: usize,
501 output_qubits: usize,
503 strategy: PoolingStrategy,
505 name: String,
507}
508
509#[derive(Debug, Clone, Copy)]
510pub enum PoolingStrategy {
511 TraceOut,
513 MeasureCondition,
515 Parameterized,
517}
518
519impl QuantumPoolingLayer {
520 pub fn new(input_qubits: usize, strategy: PoolingStrategy) -> Self {
522 let output_qubits = input_qubits / 2;
523
524 Self {
525 input_qubits,
526 output_qubits,
527 strategy,
528 name: format!("QuantumPoolingLayer_{strategy:?}"),
529 }
530 }
531}
532
533impl QMLLayer for QuantumPoolingLayer {
534 fn num_qubits(&self) -> usize {
535 self.input_qubits
536 }
537
538 fn parameters(&self) -> &[Parameter] {
539 &[]
540 }
541
542 fn parameters_mut(&mut self) -> &mut [Parameter] {
543 &mut []
544 }
545
546 fn gates(&self) -> Vec<Box<dyn GateOp>> {
547 vec![]
550 }
551
552 fn compute_gradients(
553 &self,
554 _state: &Array1<Complex64>,
555 _loss_gradient: &Array1<Complex64>,
556 ) -> QuantRS2Result<Vec<f64>> {
557 Ok(vec![])
558 }
559
560 fn name(&self) -> &str {
561 &self.name
562 }
563}
564
565#[cfg(test)]
566mod tests {
567 use super::*;
568
569 #[test]
570 fn test_rotation_layer() {
571 let layer = RotationLayer::uniform(3, 'X').expect("rotation layer creation should succeed");
572 assert_eq!(layer.num_qubits(), 3);
573 assert_eq!(layer.parameters().len(), 3);
574
575 let gates = layer.gates();
576 assert_eq!(gates.len(), 3);
577 }
578
579 #[test]
580 fn test_entangling_layer() {
581 let layer = EntanglingLayer::new(4, EntanglementPattern::Linear);
582 assert_eq!(layer.num_qubits(), 4);
583
584 let gates = layer.gates();
585 assert_eq!(gates.len(), 3); }
587
588 #[test]
589 fn test_strongly_entangling_layer() {
590 let layer = StronglyEntanglingLayer::new(2, EntanglementPattern::Full)
591 .expect("strongly entangling layer creation should succeed");
592 assert_eq!(layer.num_qubits(), 2);
593
594 let gates = layer.gates();
595 assert_eq!(gates.len(), 7); }
597
598 #[test]
599 fn test_hardware_efficient_layer() {
600 let layer = HardwareEfficientLayer::new(3)
601 .expect("hardware efficient layer creation should succeed");
602 assert_eq!(layer.num_qubits(), 3);
603
604 let gates = layer.gates();
605 assert_eq!(gates.len(), 8); }
607}