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 ndarray::Array1;
14use num_complex::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: {}",
104 axis
105 )));
106 }
107 }
108
109 let parameters = (0..num_qubits)
110 .map(|i| Parameter {
111 name: format!("rot_{}_{}", axes[i], i),
112 value: 0.0,
113 bounds: Some((-2.0 * PI, 2.0 * PI)),
114 })
115 .collect();
116
117 let name = format!("RotationLayer_{}", axes.iter().collect::<String>());
118
119 Ok(Self {
120 num_qubits,
121 axes,
122 parameters,
123 name,
124 })
125 }
126
127 pub fn uniform(num_qubits: usize, axis: char) -> QuantRS2Result<Self> {
129 Self::new(num_qubits, vec![axis; num_qubits])
130 }
131}
132
133impl QMLLayer for RotationLayer {
134 fn num_qubits(&self) -> usize {
135 self.num_qubits
136 }
137
138 fn parameters(&self) -> &[Parameter] {
139 &self.parameters
140 }
141
142 fn parameters_mut(&mut self) -> &mut [Parameter] {
143 &mut self.parameters
144 }
145
146 fn gates(&self) -> Vec<Box<dyn GateOp>> {
147 self.parameters
148 .iter()
149 .enumerate()
150 .map(|(i, param)| {
151 let qubit = QubitId(i as u32);
152 let gate: Box<dyn GateOp> = match self.axes[i] {
153 'X' => Box::new(ParametricRotationX::new(qubit, param.value)),
154 'Y' => Box::new(ParametricRotationY::new(qubit, param.value)),
155 'Z' => Box::new(ParametricRotationZ::new(qubit, param.value)),
156 _ => unreachable!(),
157 };
158 gate
159 })
160 .collect()
161 }
162
163 fn compute_gradients(
164 &self,
165 _state: &Array1<Complex64>,
166 _loss_gradient: &Array1<Complex64>,
167 ) -> QuantRS2Result<Vec<f64>> {
168 let gradients = vec![0.0; self.parameters.len()];
171 Ok(gradients)
172 }
173
174 fn name(&self) -> &str {
175 &self.name
176 }
177}
178
179#[derive(Debug, Clone)]
181pub struct EntanglingLayer {
182 num_qubits: usize,
184 pattern: EntanglementPattern,
186 parameters: Vec<Parameter>,
188 parameterized: bool,
190 name: String,
192}
193
194impl EntanglingLayer {
195 pub fn new(num_qubits: usize, pattern: EntanglementPattern) -> Self {
197 let name = format!("EntanglingLayer_{:?}", pattern);
198
199 Self {
200 num_qubits,
201 pattern,
202 parameters: vec![],
203 parameterized: false,
204 name,
205 }
206 }
207
208 pub fn parameterized(num_qubits: usize, pattern: EntanglementPattern) -> Self {
210 let pairs = create_entangling_gates(num_qubits, pattern);
211 let parameters = pairs
212 .iter()
213 .enumerate()
214 .map(|(_i, (ctrl, tgt))| Parameter {
215 name: format!("entangle_{}_{}", ctrl.0, tgt.0),
216 value: 0.0,
217 bounds: Some((-PI, PI)),
218 })
219 .collect();
220
221 let name = format!("ParameterizedEntanglingLayer_{:?}", pattern);
222
223 Self {
224 num_qubits,
225 pattern,
226 parameters,
227 parameterized: true,
228 name,
229 }
230 }
231}
232
233impl QMLLayer for EntanglingLayer {
234 fn num_qubits(&self) -> usize {
235 self.num_qubits
236 }
237
238 fn parameters(&self) -> &[Parameter] {
239 &self.parameters
240 }
241
242 fn parameters_mut(&mut self) -> &mut [Parameter] {
243 &mut self.parameters
244 }
245
246 fn gates(&self) -> Vec<Box<dyn GateOp>> {
247 let pairs = create_entangling_gates(self.num_qubits, self.pattern);
248
249 if self.parameterized {
250 pairs
252 .iter()
253 .zip(self.parameters.iter())
254 .map(|((ctrl, tgt), _param)| {
255 Box::new(CNOT {
257 control: *ctrl,
258 target: *tgt,
259 }) as Box<dyn GateOp>
260 })
261 .collect()
262 } else {
263 pairs
265 .iter()
266 .map(|(ctrl, tgt)| {
267 Box::new(CNOT {
268 control: *ctrl,
269 target: *tgt,
270 }) as Box<dyn GateOp>
271 })
272 .collect()
273 }
274 }
275
276 fn compute_gradients(
277 &self,
278 _state: &Array1<Complex64>,
279 _loss_gradient: &Array1<Complex64>,
280 ) -> QuantRS2Result<Vec<f64>> {
281 if self.parameterized {
282 Ok(vec![0.0; self.parameters.len()])
284 } else {
285 Ok(vec![])
287 }
288 }
289
290 fn name(&self) -> &str {
291 &self.name
292 }
293}
294
295#[derive(Debug, Clone)]
297pub struct StronglyEntanglingLayer {
298 num_qubits: usize,
300 rotation_layers: Vec<RotationLayer>,
302 entangling_layer: EntanglingLayer,
304 total_parameters: usize,
306 name: String,
308}
309
310impl StronglyEntanglingLayer {
311 pub fn new(num_qubits: usize, pattern: EntanglementPattern) -> QuantRS2Result<Self> {
313 let rotation_layers = vec![
314 RotationLayer::uniform(num_qubits, 'X')?,
315 RotationLayer::uniform(num_qubits, 'Y')?,
316 RotationLayer::uniform(num_qubits, 'Z')?,
317 ];
318
319 let entangling_layer = EntanglingLayer::new(num_qubits, pattern);
320
321 let total_parameters = rotation_layers
322 .iter()
323 .map(|layer| layer.parameters().len())
324 .sum::<usize>()
325 + entangling_layer.parameters().len();
326
327 let name = format!("StronglyEntanglingLayer_{:?}", pattern);
328
329 Ok(Self {
330 num_qubits,
331 rotation_layers,
332 entangling_layer,
333 total_parameters,
334 name,
335 })
336 }
337}
338
339impl QMLLayer for StronglyEntanglingLayer {
340 fn num_qubits(&self) -> usize {
341 self.num_qubits
342 }
343
344 fn parameters(&self) -> &[Parameter] {
345 &[]
348 }
349
350 fn parameters_mut(&mut self) -> &mut [Parameter] {
351 &mut []
353 }
354
355 fn set_parameters(&mut self, values: &[f64]) -> QuantRS2Result<()> {
356 if values.len() != self.total_parameters {
357 return Err(QuantRS2Error::InvalidInput(format!(
358 "Expected {} parameters, got {}",
359 self.total_parameters,
360 values.len()
361 )));
362 }
363
364 let mut offset = 0;
365 for layer in &mut self.rotation_layers {
366 let n = layer.parameters().len();
367 layer.set_parameters(&values[offset..offset + n])?;
368 offset += n;
369 }
370
371 if self.entangling_layer.parameterized {
372 self.entangling_layer.set_parameters(&values[offset..])?;
373 }
374
375 Ok(())
376 }
377
378 fn gates(&self) -> Vec<Box<dyn GateOp>> {
379 let mut gates = Vec::new();
380
381 for layer in &self.rotation_layers {
383 gates.extend(layer.gates());
384 }
385
386 gates.extend(self.entangling_layer.gates());
388
389 gates
390 }
391
392 fn compute_gradients(
393 &self,
394 state: &Array1<Complex64>,
395 loss_gradient: &Array1<Complex64>,
396 ) -> QuantRS2Result<Vec<f64>> {
397 let mut gradients = Vec::new();
398
399 for layer in &self.rotation_layers {
400 gradients.extend(layer.compute_gradients(state, loss_gradient)?);
401 }
402
403 if self.entangling_layer.parameterized {
404 gradients.extend(
405 self.entangling_layer
406 .compute_gradients(state, loss_gradient)?,
407 );
408 }
409
410 Ok(gradients)
411 }
412
413 fn name(&self) -> &str {
414 &self.name
415 }
416}
417
418#[derive(Debug, Clone)]
420pub struct HardwareEfficientLayer {
421 num_qubits: usize,
423 single_qubit_gates: Vec<RotationLayer>,
425 entangling_gates: EntanglingLayer,
427 name: String,
429}
430
431impl HardwareEfficientLayer {
432 pub fn new(num_qubits: usize) -> QuantRS2Result<Self> {
434 let single_qubit_gates = vec![
436 RotationLayer::uniform(num_qubits, 'Y')?,
437 RotationLayer::uniform(num_qubits, 'Z')?,
438 ];
439
440 let entangling_gates = EntanglingLayer::new(num_qubits, EntanglementPattern::Linear);
442
443 Ok(Self {
444 num_qubits,
445 single_qubit_gates,
446 entangling_gates,
447 name: "HardwareEfficientLayer".to_string(),
448 })
449 }
450}
451
452impl QMLLayer for HardwareEfficientLayer {
453 fn num_qubits(&self) -> usize {
454 self.num_qubits
455 }
456
457 fn parameters(&self) -> &[Parameter] {
458 &[]
460 }
461
462 fn parameters_mut(&mut self) -> &mut [Parameter] {
463 &mut []
464 }
465
466 fn gates(&self) -> Vec<Box<dyn GateOp>> {
467 let mut gates = Vec::new();
468
469 for layer in &self.single_qubit_gates {
470 gates.extend(layer.gates());
471 }
472
473 gates.extend(self.entangling_gates.gates());
474
475 gates
476 }
477
478 fn compute_gradients(
479 &self,
480 state: &Array1<Complex64>,
481 loss_gradient: &Array1<Complex64>,
482 ) -> QuantRS2Result<Vec<f64>> {
483 let mut gradients = Vec::new();
484
485 for layer in &self.single_qubit_gates {
486 gradients.extend(layer.compute_gradients(state, loss_gradient)?);
487 }
488
489 Ok(gradients)
490 }
491
492 fn name(&self) -> &str {
493 &self.name
494 }
495}
496
497#[derive(Debug, Clone)]
499pub struct QuantumPoolingLayer {
500 input_qubits: usize,
502 output_qubits: usize,
504 strategy: PoolingStrategy,
506 name: String,
508}
509
510#[derive(Debug, Clone, Copy)]
511pub enum PoolingStrategy {
512 TraceOut,
514 MeasureCondition,
516 Parameterized,
518}
519
520impl QuantumPoolingLayer {
521 pub fn new(input_qubits: usize, strategy: PoolingStrategy) -> Self {
523 let output_qubits = input_qubits / 2;
524
525 Self {
526 input_qubits,
527 output_qubits,
528 strategy,
529 name: format!("QuantumPoolingLayer_{:?}", strategy),
530 }
531 }
532}
533
534impl QMLLayer for QuantumPoolingLayer {
535 fn num_qubits(&self) -> usize {
536 self.input_qubits
537 }
538
539 fn parameters(&self) -> &[Parameter] {
540 &[]
541 }
542
543 fn parameters_mut(&mut self) -> &mut [Parameter] {
544 &mut []
545 }
546
547 fn gates(&self) -> Vec<Box<dyn GateOp>> {
548 vec![]
551 }
552
553 fn compute_gradients(
554 &self,
555 _state: &Array1<Complex64>,
556 _loss_gradient: &Array1<Complex64>,
557 ) -> QuantRS2Result<Vec<f64>> {
558 Ok(vec![])
559 }
560
561 fn name(&self) -> &str {
562 &self.name
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569
570 #[test]
571 fn test_rotation_layer() {
572 let layer = RotationLayer::uniform(3, 'X').unwrap();
573 assert_eq!(layer.num_qubits(), 3);
574 assert_eq!(layer.parameters().len(), 3);
575
576 let gates = layer.gates();
577 assert_eq!(gates.len(), 3);
578 }
579
580 #[test]
581 fn test_entangling_layer() {
582 let layer = EntanglingLayer::new(4, EntanglementPattern::Linear);
583 assert_eq!(layer.num_qubits(), 4);
584
585 let gates = layer.gates();
586 assert_eq!(gates.len(), 3); }
588
589 #[test]
590 fn test_strongly_entangling_layer() {
591 let layer = StronglyEntanglingLayer::new(2, EntanglementPattern::Full).unwrap();
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).unwrap();
601 assert_eq!(layer.num_qubits(), 3);
602
603 let gates = layer.gates();
604 assert_eq!(gates.len(), 8); }
606}