1use super::{
14 gates::{
15 TQHadamard, TQPauliX, TQPauliY, TQPauliZ, TQRx, TQRy, TQRz, TQCNOT, TQCRX, TQCRY, TQCRZ,
16 TQCZ, TQRXX, TQRYY, TQRZX, TQRZZ, TQS, TQSWAP, TQSX, TQT,
17 },
18 CType, TQDevice, TQModule, TQOperator, TQParameter,
19};
20use crate::error::{MLError, Result};
21use scirs2_core::ndarray::Array2;
22
23pub struct TQOp1QAllLayer {
25 pub n_wires: usize,
27 pub op_name: String,
29 pub has_params: bool,
31 pub trainable: bool,
33 gates: Vec<Box<dyn TQOperator>>,
35 static_mode: bool,
36}
37
38impl TQOp1QAllLayer {
39 pub fn new(
40 op_name: impl Into<String>,
41 n_wires: usize,
42 has_params: bool,
43 trainable: bool,
44 ) -> Self {
45 let op_name = op_name.into();
46 let gates: Vec<Box<dyn TQOperator>> = (0..n_wires)
47 .map(|_| create_single_qubit_gate(&op_name, has_params, trainable))
48 .collect();
49
50 Self {
51 n_wires,
52 op_name,
53 has_params,
54 trainable,
55 gates,
56 static_mode: false,
57 }
58 }
59
60 pub fn rx(n_wires: usize, trainable: bool) -> Self {
62 Self::new("rx", n_wires, true, trainable)
63 }
64
65 pub fn ry(n_wires: usize, trainable: bool) -> Self {
67 Self::new("ry", n_wires, true, trainable)
68 }
69
70 pub fn rz(n_wires: usize, trainable: bool) -> Self {
72 Self::new("rz", n_wires, true, trainable)
73 }
74
75 pub fn hadamard(n_wires: usize) -> Self {
77 Self::new("hadamard", n_wires, false, false)
78 }
79}
80
81impl TQModule for TQOp1QAllLayer {
82 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
83 for (wire, gate) in self.gates.iter_mut().enumerate() {
84 gate.apply(qdev, &[wire])?;
85 }
86 Ok(())
87 }
88
89 fn parameters(&self) -> Vec<TQParameter> {
90 self.gates.iter().flat_map(|g| g.parameters()).collect()
91 }
92
93 fn n_wires(&self) -> Option<usize> {
94 Some(self.n_wires)
95 }
96
97 fn set_n_wires(&mut self, n_wires: usize) {
98 self.n_wires = n_wires;
99 }
100
101 fn is_static_mode(&self) -> bool {
102 self.static_mode
103 }
104
105 fn static_on(&mut self) {
106 self.static_mode = true;
107 for gate in &mut self.gates {
108 gate.static_on();
109 }
110 }
111
112 fn static_off(&mut self) {
113 self.static_mode = false;
114 for gate in &mut self.gates {
115 gate.static_off();
116 }
117 }
118
119 fn name(&self) -> &str {
120 "Op1QAllLayer"
121 }
122
123 fn zero_grad(&mut self) {
124 for gate in &mut self.gates {
125 gate.zero_grad();
126 }
127 }
128}
129
130pub struct TQOp2QAllLayer {
132 pub n_wires: usize,
134 pub op_name: String,
136 pub has_params: bool,
138 pub trainable: bool,
140 pub jump: usize,
142 pub circular: bool,
144 gates: Vec<Box<dyn TQOperator>>,
146 static_mode: bool,
147}
148
149impl TQOp2QAllLayer {
150 pub fn new(
151 op_name: impl Into<String>,
152 n_wires: usize,
153 has_params: bool,
154 trainable: bool,
155 jump: usize,
156 circular: bool,
157 ) -> Self {
158 let op_name = op_name.into();
159
160 let n_pairs = if circular {
162 n_wires
163 } else {
164 n_wires.saturating_sub(jump)
165 };
166
167 let gates: Vec<Box<dyn TQOperator>> = (0..n_pairs)
168 .map(|_| create_two_qubit_gate(&op_name, has_params, trainable))
169 .collect();
170
171 Self {
172 n_wires,
173 op_name,
174 has_params,
175 trainable,
176 jump,
177 circular,
178 gates,
179 static_mode: false,
180 }
181 }
182
183 pub fn cnot(n_wires: usize, circular: bool) -> Self {
185 Self::new("cnot", n_wires, false, false, 1, circular)
186 }
187
188 pub fn cz(n_wires: usize, circular: bool) -> Self {
190 Self::new("cz", n_wires, false, false, 1, circular)
191 }
192
193 pub fn swap(n_wires: usize, circular: bool) -> Self {
195 Self::new("swap", n_wires, false, false, 1, circular)
196 }
197}
198
199impl TQModule for TQOp2QAllLayer {
200 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
201 let n_pairs = if self.circular {
202 self.n_wires
203 } else {
204 self.n_wires.saturating_sub(self.jump)
205 };
206
207 for i in 0..n_pairs {
208 let wire0 = i;
209 let wire1 = (i + self.jump) % self.n_wires;
210
211 if i < self.gates.len() {
212 self.gates[i].apply(qdev, &[wire0, wire1])?;
213 }
214 }
215 Ok(())
216 }
217
218 fn parameters(&self) -> Vec<TQParameter> {
219 self.gates.iter().flat_map(|g| g.parameters()).collect()
220 }
221
222 fn n_wires(&self) -> Option<usize> {
223 Some(self.n_wires)
224 }
225
226 fn set_n_wires(&mut self, n_wires: usize) {
227 self.n_wires = n_wires;
228 }
229
230 fn is_static_mode(&self) -> bool {
231 self.static_mode
232 }
233
234 fn static_on(&mut self) {
235 self.static_mode = true;
236 for gate in &mut self.gates {
237 gate.static_on();
238 }
239 }
240
241 fn static_off(&mut self) {
242 self.static_mode = false;
243 for gate in &mut self.gates {
244 gate.static_off();
245 }
246 }
247
248 fn name(&self) -> &str {
249 "Op2QAllLayer"
250 }
251
252 fn zero_grad(&mut self) {
253 for gate in &mut self.gates {
254 gate.zero_grad();
255 }
256 }
257}
258
259#[derive(Debug, Clone)]
261pub struct TQLayerConfig {
262 pub n_wires: usize,
263 pub n_blocks: usize,
264 pub n_layers_per_block: Option<usize>,
265}
266
267impl TQLayerConfig {
268 pub fn new(n_wires: usize, n_blocks: usize) -> Self {
269 Self {
270 n_wires,
271 n_blocks,
272 n_layers_per_block: None,
273 }
274 }
275
276 pub fn with_layers_per_block(mut self, n: usize) -> Self {
277 self.n_layers_per_block = Some(n);
278 self
279 }
280}
281
282pub struct TQBarrenLayer {
285 config: TQLayerConfig,
286 layers: Vec<Box<dyn TQModule>>,
287 static_mode: bool,
288}
289
290impl TQBarrenLayer {
291 pub fn new(config: TQLayerConfig) -> Self {
292 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
293
294 layers.push(Box::new(TQOp1QAllLayer::hadamard(config.n_wires)));
296
297 for _ in 0..config.n_blocks {
299 layers.push(Box::new(TQOp1QAllLayer::rx(config.n_wires, true)));
300 layers.push(Box::new(TQOp1QAllLayer::ry(config.n_wires, true)));
301 layers.push(Box::new(TQOp1QAllLayer::rz(config.n_wires, true)));
302 layers.push(Box::new(TQOp2QAllLayer::cz(config.n_wires, false)));
303 }
304
305 Self {
306 config,
307 layers,
308 static_mode: false,
309 }
310 }
311}
312
313impl TQModule for TQBarrenLayer {
314 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
315 for layer in &mut self.layers {
316 layer.forward(qdev)?;
317 }
318 Ok(())
319 }
320
321 fn parameters(&self) -> Vec<TQParameter> {
322 self.layers.iter().flat_map(|l| l.parameters()).collect()
323 }
324
325 fn n_wires(&self) -> Option<usize> {
326 Some(self.config.n_wires)
327 }
328
329 fn set_n_wires(&mut self, n_wires: usize) {
330 self.config.n_wires = n_wires;
331 }
332
333 fn is_static_mode(&self) -> bool {
334 self.static_mode
335 }
336
337 fn static_on(&mut self) {
338 self.static_mode = true;
339 for layer in &mut self.layers {
340 layer.static_on();
341 }
342 }
343
344 fn static_off(&mut self) {
345 self.static_mode = false;
346 for layer in &mut self.layers {
347 layer.static_off();
348 }
349 }
350
351 fn name(&self) -> &str {
352 "BarrenLayer"
353 }
354
355 fn zero_grad(&mut self) {
356 for layer in &mut self.layers {
357 layer.zero_grad();
358 }
359 }
360}
361
362pub struct TQRXYZCXLayer {
365 config: TQLayerConfig,
366 layers: Vec<Box<dyn TQModule>>,
367 static_mode: bool,
368}
369
370impl TQRXYZCXLayer {
371 pub fn new(config: TQLayerConfig) -> Self {
372 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
373
374 for _ in 0..config.n_blocks {
375 layers.push(Box::new(TQOp1QAllLayer::rx(config.n_wires, true)));
376 layers.push(Box::new(TQOp1QAllLayer::ry(config.n_wires, true)));
377 layers.push(Box::new(TQOp1QAllLayer::rz(config.n_wires, true)));
378 layers.push(Box::new(TQOp2QAllLayer::cnot(config.n_wires, true)));
379 }
380
381 Self {
382 config,
383 layers,
384 static_mode: false,
385 }
386 }
387}
388
389impl TQModule for TQRXYZCXLayer {
390 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
391 for layer in &mut self.layers {
392 layer.forward(qdev)?;
393 }
394 Ok(())
395 }
396
397 fn parameters(&self) -> Vec<TQParameter> {
398 self.layers.iter().flat_map(|l| l.parameters()).collect()
399 }
400
401 fn n_wires(&self) -> Option<usize> {
402 Some(self.config.n_wires)
403 }
404
405 fn set_n_wires(&mut self, n_wires: usize) {
406 self.config.n_wires = n_wires;
407 }
408
409 fn is_static_mode(&self) -> bool {
410 self.static_mode
411 }
412
413 fn static_on(&mut self) {
414 self.static_mode = true;
415 for layer in &mut self.layers {
416 layer.static_on();
417 }
418 }
419
420 fn static_off(&mut self) {
421 self.static_mode = false;
422 for layer in &mut self.layers {
423 layer.static_off();
424 }
425 }
426
427 fn name(&self) -> &str {
428 "RXYZCXLayer"
429 }
430
431 fn zero_grad(&mut self) {
432 for layer in &mut self.layers {
433 layer.zero_grad();
434 }
435 }
436}
437
438fn create_single_qubit_gate(name: &str, has_params: bool, trainable: bool) -> Box<dyn TQOperator> {
440 match name.to_lowercase().as_str() {
441 "rx" => Box::new(TQRx::new(has_params, trainable)),
442 "ry" => Box::new(TQRy::new(has_params, trainable)),
443 "rz" => Box::new(TQRz::new(has_params, trainable)),
444 "h" | "hadamard" => Box::new(TQHadamard::new()),
445 "x" | "paulix" => Box::new(TQPauliX::new()),
446 "y" | "pauliy" => Box::new(TQPauliY::new()),
447 "z" | "pauliz" => Box::new(TQPauliZ::new()),
448 "s" => Box::new(TQS::new()),
449 "t" => Box::new(TQT::new()),
450 "sx" => Box::new(TQSX::new()),
451 _ => Box::new(TQRy::new(has_params, trainable)), }
453}
454
455fn create_two_qubit_gate(name: &str, has_params: bool, trainable: bool) -> Box<dyn TQOperator> {
457 match name.to_lowercase().as_str() {
458 "cnot" | "cx" => Box::new(TQCNOT::new()),
459 "cz" => Box::new(TQCZ::new()),
460 "swap" => Box::new(TQSWAP::new()),
461 "rxx" => Box::new(TQRXX::new(has_params, trainable)),
463 "ryy" => Box::new(TQRYY::new(has_params, trainable)),
464 "rzz" => Box::new(TQRZZ::new(has_params, trainable)),
465 "rzx" => Box::new(TQRZX::new(has_params, trainable)),
466 "crx" => Box::new(TQCRX::new(has_params, trainable)),
468 "cry" => Box::new(TQCRY::new(has_params, trainable)),
469 "crz" => Box::new(TQCRZ::new(has_params, trainable)),
470 _ => Box::new(TQCNOT::new()), }
472}
473
474pub struct TQFarhiLayer {
478 config: TQLayerConfig,
479 layers: Vec<Box<dyn TQModule>>,
480 static_mode: bool,
481}
482
483impl TQFarhiLayer {
484 pub fn new(config: TQLayerConfig) -> Self {
485 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
486
487 for _ in 0..config.n_blocks {
488 layers.push(Box::new(TQOp2QAllLayer::new(
490 "rzx",
491 config.n_wires,
492 true,
493 true,
494 1,
495 true, )));
497 layers.push(Box::new(TQOp2QAllLayer::new(
499 "rxx",
500 config.n_wires,
501 true,
502 true,
503 1,
504 true, )));
506 }
507
508 Self {
509 config,
510 layers,
511 static_mode: false,
512 }
513 }
514}
515
516impl TQModule for TQFarhiLayer {
517 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
518 for layer in &mut self.layers {
519 layer.forward(qdev)?;
520 }
521 Ok(())
522 }
523
524 fn parameters(&self) -> Vec<TQParameter> {
525 self.layers.iter().flat_map(|l| l.parameters()).collect()
526 }
527
528 fn n_wires(&self) -> Option<usize> {
529 Some(self.config.n_wires)
530 }
531
532 fn set_n_wires(&mut self, n_wires: usize) {
533 self.config.n_wires = n_wires;
534 }
535
536 fn is_static_mode(&self) -> bool {
537 self.static_mode
538 }
539
540 fn static_on(&mut self) {
541 self.static_mode = true;
542 for layer in &mut self.layers {
543 layer.static_on();
544 }
545 }
546
547 fn static_off(&mut self) {
548 self.static_mode = false;
549 for layer in &mut self.layers {
550 layer.static_off();
551 }
552 }
553
554 fn name(&self) -> &str {
555 "FarhiLayer"
556 }
557
558 fn zero_grad(&mut self) {
559 for layer in &mut self.layers {
560 layer.zero_grad();
561 }
562 }
563}
564
565pub struct TQMaxwellLayer {
569 config: TQLayerConfig,
570 layers: Vec<Box<dyn TQModule>>,
571 static_mode: bool,
572}
573
574impl TQMaxwellLayer {
575 pub fn new(config: TQLayerConfig) -> Self {
576 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
577
578 for _ in 0..config.n_blocks {
579 layers.push(Box::new(TQOp1QAllLayer::rx(config.n_wires, true)));
581 layers.push(Box::new(TQOp1QAllLayer::new(
582 "s",
583 config.n_wires,
584 false,
585 false,
586 )));
587 layers.push(Box::new(TQOp2QAllLayer::new(
588 "cnot",
589 config.n_wires,
590 false,
591 false,
592 1,
593 true,
594 )));
595
596 layers.push(Box::new(TQOp1QAllLayer::ry(config.n_wires, true)));
598 layers.push(Box::new(TQOp1QAllLayer::new(
599 "t",
600 config.n_wires,
601 false,
602 false,
603 )));
604 layers.push(Box::new(TQOp2QAllLayer::new(
605 "swap",
606 config.n_wires,
607 false,
608 false,
609 1,
610 true,
611 )));
612
613 layers.push(Box::new(TQOp1QAllLayer::rz(config.n_wires, true)));
615 layers.push(Box::new(TQOp1QAllLayer::hadamard(config.n_wires)));
616 layers.push(Box::new(TQOp2QAllLayer::new(
617 "cnot",
618 config.n_wires,
619 false,
620 false,
621 1,
622 true,
623 )));
624 }
625
626 Self {
627 config,
628 layers,
629 static_mode: false,
630 }
631 }
632}
633
634impl TQModule for TQMaxwellLayer {
635 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
636 for layer in &mut self.layers {
637 layer.forward(qdev)?;
638 }
639 Ok(())
640 }
641
642 fn parameters(&self) -> Vec<TQParameter> {
643 self.layers.iter().flat_map(|l| l.parameters()).collect()
644 }
645
646 fn n_wires(&self) -> Option<usize> {
647 Some(self.config.n_wires)
648 }
649
650 fn set_n_wires(&mut self, n_wires: usize) {
651 self.config.n_wires = n_wires;
652 }
653
654 fn is_static_mode(&self) -> bool {
655 self.static_mode
656 }
657
658 fn static_on(&mut self) {
659 self.static_mode = true;
660 for layer in &mut self.layers {
661 layer.static_on();
662 }
663 }
664
665 fn static_off(&mut self) {
666 self.static_mode = false;
667 for layer in &mut self.layers {
668 layer.static_off();
669 }
670 }
671
672 fn name(&self) -> &str {
673 "MaxwellLayer"
674 }
675
676 fn zero_grad(&mut self) {
677 for layer in &mut self.layers {
678 layer.zero_grad();
679 }
680 }
681}
682
683pub struct TQSethLayer {
687 config: TQLayerConfig,
688 layers: Vec<Box<dyn TQModule>>,
689 static_mode: bool,
690}
691
692impl TQSethLayer {
693 pub fn new(config: TQLayerConfig) -> Self {
694 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
695
696 for _ in 0..config.n_blocks {
697 layers.push(Box::new(TQOp1QAllLayer::ry(config.n_wires, true)));
698 layers.push(Box::new(TQOp1QAllLayer::rz(config.n_wires, true)));
699 layers.push(Box::new(TQOp2QAllLayer::cz(config.n_wires, true)));
700 }
701
702 Self {
703 config,
704 layers,
705 static_mode: false,
706 }
707 }
708}
709
710impl TQModule for TQSethLayer {
711 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
712 for layer in &mut self.layers {
713 layer.forward(qdev)?;
714 }
715 Ok(())
716 }
717
718 fn parameters(&self) -> Vec<TQParameter> {
719 self.layers.iter().flat_map(|l| l.parameters()).collect()
720 }
721
722 fn n_wires(&self) -> Option<usize> {
723 Some(self.config.n_wires)
724 }
725
726 fn set_n_wires(&mut self, n_wires: usize) {
727 self.config.n_wires = n_wires;
728 }
729
730 fn is_static_mode(&self) -> bool {
731 self.static_mode
732 }
733
734 fn static_on(&mut self) {
735 self.static_mode = true;
736 for layer in &mut self.layers {
737 layer.static_on();
738 }
739 }
740
741 fn static_off(&mut self) {
742 self.static_mode = false;
743 for layer in &mut self.layers {
744 layer.static_off();
745 }
746 }
747
748 fn name(&self) -> &str {
749 "SethLayer"
750 }
751
752 fn zero_grad(&mut self) {
753 for layer in &mut self.layers {
754 layer.zero_grad();
755 }
756 }
757}
758
759pub struct TQStrongEntanglingLayer {
763 config: TQLayerConfig,
764 layers: Vec<Box<dyn TQModule>>,
765 static_mode: bool,
766}
767
768impl TQStrongEntanglingLayer {
769 pub fn new(config: TQLayerConfig) -> Self {
770 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
771
772 for block_idx in 0..config.n_blocks {
773 layers.push(Box::new(TQOp1QAllLayer::rx(config.n_wires, true)));
775 layers.push(Box::new(TQOp1QAllLayer::ry(config.n_wires, true)));
776 layers.push(Box::new(TQOp1QAllLayer::rz(config.n_wires, true)));
777
778 let jump = (block_idx % config.n_wires) + 1;
780 layers.push(Box::new(TQOp2QAllLayer::new(
781 "cnot",
782 config.n_wires,
783 false,
784 false,
785 jump,
786 true, )));
788 }
789
790 Self {
791 config,
792 layers,
793 static_mode: false,
794 }
795 }
796}
797
798impl TQModule for TQStrongEntanglingLayer {
799 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
800 for layer in &mut self.layers {
801 layer.forward(qdev)?;
802 }
803 Ok(())
804 }
805
806 fn parameters(&self) -> Vec<TQParameter> {
807 self.layers.iter().flat_map(|l| l.parameters()).collect()
808 }
809
810 fn n_wires(&self) -> Option<usize> {
811 Some(self.config.n_wires)
812 }
813
814 fn set_n_wires(&mut self, n_wires: usize) {
815 self.config.n_wires = n_wires;
816 }
817
818 fn is_static_mode(&self) -> bool {
819 self.static_mode
820 }
821
822 fn static_on(&mut self) {
823 self.static_mode = true;
824 for layer in &mut self.layers {
825 layer.static_on();
826 }
827 }
828
829 fn static_off(&mut self) {
830 self.static_mode = false;
831 for layer in &mut self.layers {
832 layer.static_off();
833 }
834 }
835
836 fn name(&self) -> &str {
837 "StrongEntanglingLayer"
838 }
839
840 fn zero_grad(&mut self) {
841 for layer in &mut self.layers {
842 layer.zero_grad();
843 }
844 }
845}
846
847pub struct TQQFTLayer {
850 n_wires: usize,
851 wires: Vec<usize>,
852 do_swaps: bool,
853 inverse: bool,
854 static_mode: bool,
855}
856
857impl TQQFTLayer {
858 pub fn new(n_wires: usize, do_swaps: bool, inverse: bool) -> Self {
859 Self {
860 n_wires,
861 wires: (0..n_wires).collect(),
862 do_swaps,
863 inverse,
864 static_mode: false,
865 }
866 }
867
868 pub fn standard(n_wires: usize) -> Self {
870 Self::new(n_wires, true, false)
871 }
872
873 pub fn inverse(n_wires: usize) -> Self {
875 Self::new(n_wires, true, true)
876 }
877
878 pub fn no_swaps(n_wires: usize) -> Self {
880 Self::new(n_wires, false, false)
881 }
882
883 pub fn with_wires(wires: Vec<usize>, do_swaps: bool, inverse: bool) -> Self {
885 let n_wires = wires.len();
886 Self {
887 n_wires,
888 wires,
889 do_swaps,
890 inverse,
891 static_mode: false,
892 }
893 }
894}
895
896impl TQModule for TQQFTLayer {
897 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
898 use super::gates::{TQHadamard, TQCU1, TQSWAP};
899 use std::f64::consts::PI;
900
901 if self.inverse {
902 if self.do_swaps {
904 for wire in 0..(self.n_wires / 2) {
905 let mut swap_gate = TQSWAP::new();
906 swap_gate.apply(
907 qdev,
908 &[self.wires[wire], self.wires[self.n_wires - wire - 1]],
909 )?;
910 }
911 }
912
913 for top_wire in (0..self.n_wires).rev() {
914 for wire in ((top_wire + 1)..self.n_wires).rev() {
915 let lam = -PI / (1 << (wire - top_wire)) as f64;
916 let mut cu1_gate = TQCU1::new(true, false);
917 cu1_gate.apply_with_params(
918 qdev,
919 &[self.wires[wire], self.wires[top_wire]],
920 Some(&[lam]),
921 )?;
922 }
923 let mut h_gate = TQHadamard::new();
924 h_gate.apply(qdev, &[self.wires[top_wire]])?;
925 }
926 } else {
927 for top_wire in 0..self.n_wires {
929 let mut h_gate = TQHadamard::new();
930 h_gate.apply(qdev, &[self.wires[top_wire]])?;
931
932 for wire in (top_wire + 1)..self.n_wires {
933 let lam = PI / (1 << (wire - top_wire)) as f64;
934 let mut cu1_gate = TQCU1::new(true, false);
935 cu1_gate.apply_with_params(
936 qdev,
937 &[self.wires[wire], self.wires[top_wire]],
938 Some(&[lam]),
939 )?;
940 }
941 }
942
943 if self.do_swaps {
944 for wire in 0..(self.n_wires / 2) {
945 let mut swap_gate = TQSWAP::new();
946 swap_gate.apply(
947 qdev,
948 &[self.wires[wire], self.wires[self.n_wires - wire - 1]],
949 )?;
950 }
951 }
952 }
953
954 Ok(())
955 }
956
957 fn parameters(&self) -> Vec<TQParameter> {
958 Vec::new() }
960
961 fn n_wires(&self) -> Option<usize> {
962 Some(self.n_wires)
963 }
964
965 fn set_n_wires(&mut self, n_wires: usize) {
966 self.n_wires = n_wires;
967 self.wires = (0..n_wires).collect();
968 }
969
970 fn is_static_mode(&self) -> bool {
971 self.static_mode
972 }
973
974 fn static_on(&mut self) {
975 self.static_mode = true;
976 }
977
978 fn static_off(&mut self) {
979 self.static_mode = false;
980 }
981
982 fn name(&self) -> &str {
983 if self.inverse {
984 "InverseQFTLayer"
985 } else {
986 "QFTLayer"
987 }
988 }
989}
990
991#[derive(Debug, Clone, Copy, PartialEq)]
993pub enum EntanglementPattern {
994 Linear,
996 ReverseLinear,
998 Circular,
1000 Full,
1002}
1003
1004pub struct TQTwoLocalLayer {
1007 n_wires: usize,
1008 rotation_ops: Vec<String>,
1009 entanglement_ops: Vec<String>,
1010 entanglement_pattern: EntanglementPattern,
1011 reps: usize,
1012 skip_final_rotation: bool,
1013 layers: Vec<Box<dyn TQModule>>,
1014 static_mode: bool,
1015}
1016
1017impl TQTwoLocalLayer {
1018 pub fn new(
1019 n_wires: usize,
1020 rotation_ops: Vec<&str>,
1021 entanglement_ops: Vec<&str>,
1022 entanglement_pattern: EntanglementPattern,
1023 reps: usize,
1024 skip_final_rotation: bool,
1025 ) -> Self {
1026 let rotation_ops: Vec<String> = rotation_ops.iter().map(|s| s.to_string()).collect();
1027 let entanglement_ops: Vec<String> =
1028 entanglement_ops.iter().map(|s| s.to_string()).collect();
1029
1030 let layers = Self::build_layers(
1031 n_wires,
1032 &rotation_ops,
1033 &entanglement_ops,
1034 entanglement_pattern,
1035 reps,
1036 skip_final_rotation,
1037 );
1038
1039 Self {
1040 n_wires,
1041 rotation_ops,
1042 entanglement_ops,
1043 entanglement_pattern,
1044 reps,
1045 skip_final_rotation,
1046 layers,
1047 static_mode: false,
1048 }
1049 }
1050
1051 fn build_layers(
1052 n_wires: usize,
1053 rotation_ops: &[String],
1054 entanglement_ops: &[String],
1055 entanglement_pattern: EntanglementPattern,
1056 reps: usize,
1057 skip_final_rotation: bool,
1058 ) -> Vec<Box<dyn TQModule>> {
1059 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
1060
1061 let circular = matches!(entanglement_pattern, EntanglementPattern::Circular);
1062
1063 for _ in 0..reps {
1064 for op in rotation_ops {
1066 layers.push(Box::new(TQOp1QAllLayer::new(op, n_wires, true, true)));
1067 }
1068
1069 if entanglement_pattern == EntanglementPattern::Full {
1071 for op in entanglement_ops {
1073 layers.push(Box::new(TQOp2QDenseLayer::new(op, n_wires)));
1074 }
1075 } else {
1076 for op in entanglement_ops {
1077 layers.push(Box::new(TQOp2QAllLayer::new(
1078 op, n_wires, false, false, 1, circular,
1079 )));
1080 }
1081 }
1082 }
1083
1084 if !skip_final_rotation {
1086 for op in rotation_ops {
1087 layers.push(Box::new(TQOp1QAllLayer::new(op, n_wires, true, true)));
1088 }
1089 }
1090
1091 layers
1092 }
1093}
1094
1095impl TQModule for TQTwoLocalLayer {
1096 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1097 for layer in &mut self.layers {
1098 layer.forward(qdev)?;
1099 }
1100 Ok(())
1101 }
1102
1103 fn parameters(&self) -> Vec<TQParameter> {
1104 self.layers.iter().flat_map(|l| l.parameters()).collect()
1105 }
1106
1107 fn n_wires(&self) -> Option<usize> {
1108 Some(self.n_wires)
1109 }
1110
1111 fn set_n_wires(&mut self, n_wires: usize) {
1112 self.n_wires = n_wires;
1113 self.layers = Self::build_layers(
1114 n_wires,
1115 &self.rotation_ops,
1116 &self.entanglement_ops,
1117 self.entanglement_pattern,
1118 self.reps,
1119 self.skip_final_rotation,
1120 );
1121 }
1122
1123 fn is_static_mode(&self) -> bool {
1124 self.static_mode
1125 }
1126
1127 fn static_on(&mut self) {
1128 self.static_mode = true;
1129 for layer in &mut self.layers {
1130 layer.static_on();
1131 }
1132 }
1133
1134 fn static_off(&mut self) {
1135 self.static_mode = false;
1136 for layer in &mut self.layers {
1137 layer.static_off();
1138 }
1139 }
1140
1141 fn name(&self) -> &str {
1142 "TwoLocalLayer"
1143 }
1144
1145 fn zero_grad(&mut self) {
1146 for layer in &mut self.layers {
1147 layer.zero_grad();
1148 }
1149 }
1150}
1151
1152pub struct TQEfficientSU2Layer {
1155 inner: TQTwoLocalLayer,
1156}
1157
1158impl TQEfficientSU2Layer {
1159 pub fn new(n_wires: usize, reps: usize, entanglement: EntanglementPattern) -> Self {
1160 Self {
1161 inner: TQTwoLocalLayer::new(
1162 n_wires,
1163 vec!["ry", "rz"],
1164 vec!["cnot"],
1165 entanglement,
1166 reps,
1167 false,
1168 ),
1169 }
1170 }
1171
1172 pub fn default_entanglement(n_wires: usize, reps: usize) -> Self {
1174 Self::new(n_wires, reps, EntanglementPattern::ReverseLinear)
1175 }
1176}
1177
1178impl TQModule for TQEfficientSU2Layer {
1179 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1180 self.inner.forward(qdev)
1181 }
1182
1183 fn parameters(&self) -> Vec<TQParameter> {
1184 self.inner.parameters()
1185 }
1186
1187 fn n_wires(&self) -> Option<usize> {
1188 self.inner.n_wires()
1189 }
1190
1191 fn set_n_wires(&mut self, n_wires: usize) {
1192 self.inner.set_n_wires(n_wires);
1193 }
1194
1195 fn is_static_mode(&self) -> bool {
1196 self.inner.is_static_mode()
1197 }
1198
1199 fn static_on(&mut self) {
1200 self.inner.static_on();
1201 }
1202
1203 fn static_off(&mut self) {
1204 self.inner.static_off();
1205 }
1206
1207 fn name(&self) -> &str {
1208 "EfficientSU2Layer"
1209 }
1210
1211 fn zero_grad(&mut self) {
1212 self.inner.zero_grad();
1213 }
1214}
1215
1216pub struct TQRealAmplitudesLayer {
1219 inner: TQTwoLocalLayer,
1220}
1221
1222impl TQRealAmplitudesLayer {
1223 pub fn new(n_wires: usize, reps: usize, entanglement: EntanglementPattern) -> Self {
1224 Self {
1225 inner: TQTwoLocalLayer::new(
1226 n_wires,
1227 vec!["ry"],
1228 vec!["cnot"],
1229 entanglement,
1230 reps,
1231 false,
1232 ),
1233 }
1234 }
1235
1236 pub fn default_entanglement(n_wires: usize, reps: usize) -> Self {
1238 Self::new(n_wires, reps, EntanglementPattern::ReverseLinear)
1239 }
1240}
1241
1242impl TQModule for TQRealAmplitudesLayer {
1243 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1244 self.inner.forward(qdev)
1245 }
1246
1247 fn parameters(&self) -> Vec<TQParameter> {
1248 self.inner.parameters()
1249 }
1250
1251 fn n_wires(&self) -> Option<usize> {
1252 self.inner.n_wires()
1253 }
1254
1255 fn set_n_wires(&mut self, n_wires: usize) {
1256 self.inner.set_n_wires(n_wires);
1257 }
1258
1259 fn is_static_mode(&self) -> bool {
1260 self.inner.is_static_mode()
1261 }
1262
1263 fn static_on(&mut self) {
1264 self.inner.static_on();
1265 }
1266
1267 fn static_off(&mut self) {
1268 self.inner.static_off();
1269 }
1270
1271 fn name(&self) -> &str {
1272 "RealAmplitudesLayer"
1273 }
1274
1275 fn zero_grad(&mut self) {
1276 self.inner.zero_grad();
1277 }
1278}
1279
1280pub struct TQOp2QDenseLayer {
1283 n_wires: usize,
1284 op_name: String,
1285 gates: Vec<Box<dyn TQOperator>>,
1286 static_mode: bool,
1287}
1288
1289impl TQOp2QDenseLayer {
1290 pub fn new(op_name: impl Into<String>, n_wires: usize) -> Self {
1291 let op_name = op_name.into();
1292 let n_pairs = n_wires * (n_wires - 1) / 2;
1293 let gates: Vec<Box<dyn TQOperator>> = (0..n_pairs)
1294 .map(|_| create_two_qubit_gate(&op_name, false, false))
1295 .collect();
1296
1297 Self {
1298 n_wires,
1299 op_name,
1300 gates,
1301 static_mode: false,
1302 }
1303 }
1304
1305 pub fn cnot(n_wires: usize) -> Self {
1307 Self::new("cnot", n_wires)
1308 }
1309
1310 pub fn cz(n_wires: usize) -> Self {
1312 Self::new("cz", n_wires)
1313 }
1314}
1315
1316impl TQModule for TQOp2QDenseLayer {
1317 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1318 let mut gate_idx = 0;
1319 for i in 0..self.n_wires {
1320 for j in (i + 1)..self.n_wires {
1321 if gate_idx < self.gates.len() {
1322 self.gates[gate_idx].apply(qdev, &[i, j])?;
1323 gate_idx += 1;
1324 }
1325 }
1326 }
1327 Ok(())
1328 }
1329
1330 fn parameters(&self) -> Vec<TQParameter> {
1331 self.gates.iter().flat_map(|g| g.parameters()).collect()
1332 }
1333
1334 fn n_wires(&self) -> Option<usize> {
1335 Some(self.n_wires)
1336 }
1337
1338 fn set_n_wires(&mut self, n_wires: usize) {
1339 self.n_wires = n_wires;
1340 }
1341
1342 fn is_static_mode(&self) -> bool {
1343 self.static_mode
1344 }
1345
1346 fn static_on(&mut self) {
1347 self.static_mode = true;
1348 for gate in &mut self.gates {
1349 gate.static_on();
1350 }
1351 }
1352
1353 fn static_off(&mut self) {
1354 self.static_mode = false;
1355 for gate in &mut self.gates {
1356 gate.static_off();
1357 }
1358 }
1359
1360 fn name(&self) -> &str {
1361 "Op2QDenseLayer"
1362 }
1363
1364 fn zero_grad(&mut self) {
1365 for gate in &mut self.gates {
1366 gate.zero_grad();
1367 }
1368 }
1369}
1370
1371pub struct TQRandomLayer {
1373 n_wires: usize,
1374 n_ops: usize,
1375 rotation_ops: Vec<String>,
1376 entanglement_ops: Vec<String>,
1377 seed: Option<u64>,
1378 static_mode: bool,
1379 gate_sequence: Vec<(String, Vec<usize>)>,
1381}
1382
1383impl TQRandomLayer {
1384 pub fn new(
1385 n_wires: usize,
1386 n_ops: usize,
1387 rotation_ops: Vec<&str>,
1388 entanglement_ops: Vec<&str>,
1389 seed: Option<u64>,
1390 ) -> Self {
1391 let rotation_ops: Vec<String> = rotation_ops.iter().map(|s| s.to_string()).collect();
1392 let entanglement_ops: Vec<String> =
1393 entanglement_ops.iter().map(|s| s.to_string()).collect();
1394
1395 let gate_sequence =
1396 Self::generate_sequence(n_wires, n_ops, &rotation_ops, &entanglement_ops, seed);
1397
1398 Self {
1399 n_wires,
1400 n_ops,
1401 rotation_ops,
1402 entanglement_ops,
1403 seed,
1404 static_mode: false,
1405 gate_sequence,
1406 }
1407 }
1408
1409 fn generate_sequence(
1410 n_wires: usize,
1411 n_ops: usize,
1412 rotation_ops: &[String],
1413 entanglement_ops: &[String],
1414 seed: Option<u64>,
1415 ) -> Vec<(String, Vec<usize>)> {
1416 let mut sequence = Vec::with_capacity(n_ops);
1417
1418 if let Some(s) = seed {
1419 fastrand::seed(s);
1420 }
1421
1422 let all_ops: Vec<&String> = rotation_ops.iter().chain(entanglement_ops.iter()).collect();
1423
1424 for _ in 0..n_ops {
1425 let op_idx = fastrand::usize(0..all_ops.len());
1426 let op_name = all_ops[op_idx].clone();
1427
1428 let wires = if rotation_ops.contains(&op_name) {
1429 vec![fastrand::usize(0..n_wires)]
1431 } else {
1432 let w0 = fastrand::usize(0..n_wires);
1434 let mut w1 = fastrand::usize(0..n_wires);
1435 while w1 == w0 {
1436 w1 = fastrand::usize(0..n_wires);
1437 }
1438 vec![w0, w1]
1439 };
1440
1441 sequence.push((op_name, wires));
1442 }
1443
1444 sequence
1445 }
1446
1447 pub fn regenerate(&mut self) {
1449 self.gate_sequence = Self::generate_sequence(
1450 self.n_wires,
1451 self.n_ops,
1452 &self.rotation_ops,
1453 &self.entanglement_ops,
1454 self.seed,
1455 );
1456 }
1457
1458 pub fn default_ops(n_wires: usize, n_ops: usize, seed: Option<u64>) -> Self {
1460 Self::new(n_wires, n_ops, vec!["rx", "ry", "rz"], vec!["cnot"], seed)
1461 }
1462}
1463
1464impl TQModule for TQRandomLayer {
1465 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1466 for (op_name, wires) in &self.gate_sequence {
1467 if wires.len() == 1 {
1468 let mut gate = create_single_qubit_gate(op_name, true, false);
1469 gate.apply(qdev, wires)?;
1470 } else {
1471 let mut gate = create_two_qubit_gate(op_name, false, false);
1472 gate.apply(qdev, wires)?;
1473 }
1474 }
1475 Ok(())
1476 }
1477
1478 fn parameters(&self) -> Vec<TQParameter> {
1479 Vec::new() }
1481
1482 fn n_wires(&self) -> Option<usize> {
1483 Some(self.n_wires)
1484 }
1485
1486 fn set_n_wires(&mut self, n_wires: usize) {
1487 self.n_wires = n_wires;
1488 self.regenerate();
1489 }
1490
1491 fn is_static_mode(&self) -> bool {
1492 self.static_mode
1493 }
1494
1495 fn static_on(&mut self) {
1496 self.static_mode = true;
1497 }
1498
1499 fn static_off(&mut self) {
1500 self.static_mode = false;
1501 }
1502
1503 fn name(&self) -> &str {
1504 "RandomLayer"
1505 }
1506}
1507
1508pub struct TQCXLayer {
1510 n_wires: usize,
1511 circular: bool,
1512 static_mode: bool,
1513}
1514
1515impl TQCXLayer {
1516 pub fn new(n_wires: usize, circular: bool) -> Self {
1517 Self {
1518 n_wires,
1519 circular,
1520 static_mode: false,
1521 }
1522 }
1523}
1524
1525impl TQModule for TQCXLayer {
1526 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1527 let n_pairs = if self.circular {
1528 self.n_wires
1529 } else {
1530 self.n_wires.saturating_sub(1)
1531 };
1532
1533 for i in 0..n_pairs {
1534 let wire0 = i;
1535 let wire1 = (i + 1) % self.n_wires;
1536 let mut gate = TQCNOT::new();
1537 gate.apply(qdev, &[wire0, wire1])?;
1538 }
1539 Ok(())
1540 }
1541
1542 fn parameters(&self) -> Vec<TQParameter> {
1543 Vec::new()
1544 }
1545
1546 fn n_wires(&self) -> Option<usize> {
1547 Some(self.n_wires)
1548 }
1549
1550 fn set_n_wires(&mut self, n_wires: usize) {
1551 self.n_wires = n_wires;
1552 }
1553
1554 fn is_static_mode(&self) -> bool {
1555 self.static_mode
1556 }
1557
1558 fn static_on(&mut self) {
1559 self.static_mode = true;
1560 }
1561
1562 fn static_off(&mut self) {
1563 self.static_mode = false;
1564 }
1565
1566 fn name(&self) -> &str {
1567 "CXLayer"
1568 }
1569}
1570
1571pub struct TQCXCXCXLayer {
1573 n_wires: usize,
1574 static_mode: bool,
1575}
1576
1577impl TQCXCXCXLayer {
1578 pub fn new(n_wires: usize) -> Self {
1579 Self {
1580 n_wires,
1581 static_mode: false,
1582 }
1583 }
1584}
1585
1586impl TQModule for TQCXCXCXLayer {
1587 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1588 for _ in 0..3 {
1590 for i in 0..(self.n_wires - 1) {
1591 let mut gate = TQCNOT::new();
1592 gate.apply(qdev, &[i, i + 1])?;
1593 }
1594 }
1595 Ok(())
1596 }
1597
1598 fn parameters(&self) -> Vec<TQParameter> {
1599 Vec::new()
1600 }
1601
1602 fn n_wires(&self) -> Option<usize> {
1603 Some(self.n_wires)
1604 }
1605
1606 fn set_n_wires(&mut self, n_wires: usize) {
1607 self.n_wires = n_wires;
1608 }
1609
1610 fn is_static_mode(&self) -> bool {
1611 self.static_mode
1612 }
1613
1614 fn static_on(&mut self) {
1615 self.static_mode = true;
1616 }
1617
1618 fn static_off(&mut self) {
1619 self.static_mode = false;
1620 }
1621
1622 fn name(&self) -> &str {
1623 "CXCXCXLayer"
1624 }
1625}
1626
1627use super::gates::{TQFSimGate, TQGivensRotation};
1632
1633pub struct TQExcitationPreservingLayer {
1645 n_wires: usize,
1646 n_blocks: usize,
1647 circular: bool,
1648 gates: Vec<TQFSimGate>,
1649 static_mode: bool,
1650}
1651
1652impl TQExcitationPreservingLayer {
1653 pub fn new(n_wires: usize, n_blocks: usize, circular: bool) -> Self {
1655 let n_pairs = if circular {
1656 n_wires
1657 } else {
1658 n_wires.saturating_sub(1)
1659 };
1660 let total_gates = n_pairs * n_blocks;
1661
1662 let gates: Vec<TQFSimGate> = (0..total_gates)
1663 .map(|_| TQFSimGate::new(true, true))
1664 .collect();
1665
1666 Self {
1667 n_wires,
1668 n_blocks,
1669 circular,
1670 gates,
1671 static_mode: false,
1672 }
1673 }
1674
1675 pub fn linear(n_wires: usize, n_blocks: usize) -> Self {
1677 Self::new(n_wires, n_blocks, false)
1678 }
1679
1680 pub fn circular(n_wires: usize, n_blocks: usize) -> Self {
1682 Self::new(n_wires, n_blocks, true)
1683 }
1684}
1685
1686impl TQModule for TQExcitationPreservingLayer {
1687 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1688 let n_pairs = if self.circular {
1689 self.n_wires
1690 } else {
1691 self.n_wires.saturating_sub(1)
1692 };
1693
1694 let mut gate_idx = 0;
1695 for _ in 0..self.n_blocks {
1696 for pair in 0..n_pairs {
1697 let w0 = pair;
1698 let w1 = (pair + 1) % self.n_wires;
1699
1700 if gate_idx < self.gates.len() {
1701 self.gates[gate_idx].apply(qdev, &[w0, w1])?;
1702 gate_idx += 1;
1703 }
1704 }
1705 }
1706 Ok(())
1707 }
1708
1709 fn parameters(&self) -> Vec<TQParameter> {
1710 self.gates.iter().flat_map(|g| g.parameters()).collect()
1711 }
1712
1713 fn n_wires(&self) -> Option<usize> {
1714 Some(self.n_wires)
1715 }
1716
1717 fn set_n_wires(&mut self, n_wires: usize) {
1718 self.n_wires = n_wires;
1719 let n_pairs = if self.circular {
1721 n_wires
1722 } else {
1723 n_wires.saturating_sub(1)
1724 };
1725 let total_gates = n_pairs * self.n_blocks;
1726 self.gates = (0..total_gates)
1727 .map(|_| TQFSimGate::new(true, true))
1728 .collect();
1729 }
1730
1731 fn is_static_mode(&self) -> bool {
1732 self.static_mode
1733 }
1734
1735 fn static_on(&mut self) {
1736 self.static_mode = true;
1737 for gate in &mut self.gates {
1738 gate.static_on();
1739 }
1740 }
1741
1742 fn static_off(&mut self) {
1743 self.static_mode = false;
1744 for gate in &mut self.gates {
1745 gate.static_off();
1746 }
1747 }
1748
1749 fn name(&self) -> &str {
1750 "ExcitationPreservingLayer"
1751 }
1752
1753 fn zero_grad(&mut self) {
1754 for gate in &mut self.gates {
1755 gate.zero_grad();
1756 }
1757 }
1758}
1759
1760pub struct TQParticleConservingLayer {
1769 n_wires: usize,
1770 n_blocks: usize,
1771 pattern: GivensPattern,
1772 gates: Vec<TQGivensRotation>,
1773 static_mode: bool,
1774}
1775
1776#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1778pub enum GivensPattern {
1779 Adjacent,
1781 Staircase,
1783 Bricklayer,
1785}
1786
1787impl TQParticleConservingLayer {
1788 pub fn new(n_wires: usize, n_blocks: usize, pattern: GivensPattern) -> Self {
1790 let n_gates = Self::count_gates(n_wires, n_blocks, pattern);
1791
1792 let gates: Vec<TQGivensRotation> = (0..n_gates)
1793 .map(|_| TQGivensRotation::new(true, true))
1794 .collect();
1795
1796 Self {
1797 n_wires,
1798 n_blocks,
1799 pattern,
1800 gates,
1801 static_mode: false,
1802 }
1803 }
1804
1805 pub fn adjacent(n_wires: usize, n_blocks: usize) -> Self {
1807 Self::new(n_wires, n_blocks, GivensPattern::Adjacent)
1808 }
1809
1810 pub fn staircase(n_wires: usize, n_blocks: usize) -> Self {
1812 Self::new(n_wires, n_blocks, GivensPattern::Staircase)
1813 }
1814
1815 pub fn bricklayer(n_wires: usize, n_blocks: usize) -> Self {
1817 Self::new(n_wires, n_blocks, GivensPattern::Bricklayer)
1818 }
1819
1820 fn count_gates(n_wires: usize, n_blocks: usize, pattern: GivensPattern) -> usize {
1821 match pattern {
1822 GivensPattern::Adjacent => (n_wires - 1) * n_blocks,
1823 GivensPattern::Staircase => {
1824 (n_wires - 1) * 2 * n_blocks
1827 }
1828 GivensPattern::Bricklayer => {
1829 let even = n_wires / 2;
1831 let odd = (n_wires - 1) / 2;
1832 (even + odd) * n_blocks
1833 }
1834 }
1835 }
1836
1837 fn get_wire_pairs(&self) -> Vec<(usize, usize)> {
1838 let mut pairs = Vec::new();
1839
1840 match self.pattern {
1841 GivensPattern::Adjacent => {
1842 for _ in 0..self.n_blocks {
1843 for i in 0..(self.n_wires - 1) {
1844 pairs.push((i, i + 1));
1845 }
1846 }
1847 }
1848 GivensPattern::Staircase => {
1849 for _ in 0..self.n_blocks {
1850 for i in 0..(self.n_wires - 1) {
1852 pairs.push((i, i + 1));
1853 }
1854 for i in (0..(self.n_wires - 1)).rev() {
1856 pairs.push((i, i + 1));
1857 }
1858 }
1859 }
1860 GivensPattern::Bricklayer => {
1861 for _ in 0..self.n_blocks {
1862 for i in (0..self.n_wires - 1).step_by(2) {
1864 pairs.push((i, i + 1));
1865 }
1866 for i in (1..self.n_wires - 1).step_by(2) {
1868 pairs.push((i, i + 1));
1869 }
1870 }
1871 }
1872 }
1873
1874 pairs
1875 }
1876}
1877
1878impl TQModule for TQParticleConservingLayer {
1879 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1880 let pairs = self.get_wire_pairs();
1881
1882 for (gate_idx, (w0, w1)) in pairs.iter().enumerate() {
1883 if gate_idx < self.gates.len() {
1884 self.gates[gate_idx].apply(qdev, &[*w0, *w1])?;
1885 }
1886 }
1887 Ok(())
1888 }
1889
1890 fn parameters(&self) -> Vec<TQParameter> {
1891 self.gates.iter().flat_map(|g| g.parameters()).collect()
1892 }
1893
1894 fn n_wires(&self) -> Option<usize> {
1895 Some(self.n_wires)
1896 }
1897
1898 fn set_n_wires(&mut self, n_wires: usize) {
1899 self.n_wires = n_wires;
1900 let n_gates = Self::count_gates(n_wires, self.n_blocks, self.pattern);
1901 self.gates = (0..n_gates)
1902 .map(|_| TQGivensRotation::new(true, true))
1903 .collect();
1904 }
1905
1906 fn is_static_mode(&self) -> bool {
1907 self.static_mode
1908 }
1909
1910 fn static_on(&mut self) {
1911 self.static_mode = true;
1912 for gate in &mut self.gates {
1913 gate.static_on();
1914 }
1915 }
1916
1917 fn static_off(&mut self) {
1918 self.static_mode = false;
1919 for gate in &mut self.gates {
1920 gate.static_off();
1921 }
1922 }
1923
1924 fn name(&self) -> &str {
1925 "ParticleConservingLayer"
1926 }
1927
1928 fn zero_grad(&mut self) {
1929 for gate in &mut self.gates {
1930 gate.zero_grad();
1931 }
1932 }
1933}
1934
1935pub struct TQHardwareEfficient2Layer {
1945 config: TQLayerConfig,
1946 layers: Vec<Box<dyn TQModule>>,
1947 static_mode: bool,
1948}
1949
1950impl TQHardwareEfficient2Layer {
1951 pub fn new(config: TQLayerConfig) -> Self {
1952 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
1953
1954 layers.push(Box::new(TQOp1QAllLayer::ry(config.n_wires, true)));
1956
1957 for _ in 0..config.n_blocks {
1958 layers.push(Box::new(TQOp2QAllLayer::cz(config.n_wires, true)));
1960
1961 layers.push(Box::new(TQOp1QAllLayer::rx(config.n_wires, true)));
1963
1964 layers.push(Box::new(TQOp2QAllLayer::new(
1966 "cnot",
1967 config.n_wires,
1968 false,
1969 false,
1970 1,
1971 true,
1972 )));
1973
1974 layers.push(Box::new(TQOp1QAllLayer::rz(config.n_wires, true)));
1976 }
1977
1978 Self {
1979 config,
1980 layers,
1981 static_mode: false,
1982 }
1983 }
1984}
1985
1986impl TQModule for TQHardwareEfficient2Layer {
1987 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
1988 for layer in &mut self.layers {
1989 layer.forward(qdev)?;
1990 }
1991 Ok(())
1992 }
1993
1994 fn parameters(&self) -> Vec<TQParameter> {
1995 self.layers.iter().flat_map(|l| l.parameters()).collect()
1996 }
1997
1998 fn n_wires(&self) -> Option<usize> {
1999 Some(self.config.n_wires)
2000 }
2001
2002 fn set_n_wires(&mut self, n_wires: usize) {
2003 self.config.n_wires = n_wires;
2004 }
2005
2006 fn is_static_mode(&self) -> bool {
2007 self.static_mode
2008 }
2009
2010 fn static_on(&mut self) {
2011 self.static_mode = true;
2012 for layer in &mut self.layers {
2013 layer.static_on();
2014 }
2015 }
2016
2017 fn static_off(&mut self) {
2018 self.static_mode = false;
2019 for layer in &mut self.layers {
2020 layer.static_off();
2021 }
2022 }
2023
2024 fn name(&self) -> &str {
2025 "HardwareEfficient2Layer"
2026 }
2027
2028 fn zero_grad(&mut self) {
2029 for layer in &mut self.layers {
2030 layer.zero_grad();
2031 }
2032 }
2033}
2034
2035pub struct TQUCCSDLayer {
2042 n_wires: usize,
2043 n_electrons: usize,
2044 gates: Vec<TQGivensRotation>,
2045 static_mode: bool,
2046}
2047
2048impl TQUCCSDLayer {
2049 pub fn new(n_wires: usize, n_electrons: usize) -> Self {
2055 let n_virtual = n_wires - n_electrons;
2057 let n_singles = n_electrons * n_virtual;
2058 let n_doubles = n_singles * (n_singles - 1) / 2;
2059
2060 let n_gates = n_singles.min(n_wires * 2);
2063
2064 let gates: Vec<TQGivensRotation> = (0..n_gates)
2065 .map(|_| TQGivensRotation::new(true, true))
2066 .collect();
2067
2068 Self {
2069 n_wires,
2070 n_electrons,
2071 gates,
2072 static_mode: false,
2073 }
2074 }
2075}
2076
2077impl TQModule for TQUCCSDLayer {
2078 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
2079 let mut gate_idx = 0;
2081
2082 for occ in 0..self.n_electrons.min(self.n_wires) {
2084 for virt in self.n_electrons..self.n_wires {
2085 if gate_idx < self.gates.len() {
2086 if virt > occ {
2088 self.gates[gate_idx].apply(qdev, &[occ, occ + 1])?;
2090 gate_idx += 1;
2091 }
2092 }
2093 }
2094 }
2095
2096 Ok(())
2097 }
2098
2099 fn parameters(&self) -> Vec<TQParameter> {
2100 self.gates.iter().flat_map(|g| g.parameters()).collect()
2101 }
2102
2103 fn n_wires(&self) -> Option<usize> {
2104 Some(self.n_wires)
2105 }
2106
2107 fn set_n_wires(&mut self, n_wires: usize) {
2108 self.n_wires = n_wires;
2109 }
2110
2111 fn is_static_mode(&self) -> bool {
2112 self.static_mode
2113 }
2114
2115 fn static_on(&mut self) {
2116 self.static_mode = true;
2117 for gate in &mut self.gates {
2118 gate.static_on();
2119 }
2120 }
2121
2122 fn static_off(&mut self) {
2123 self.static_mode = false;
2124 for gate in &mut self.gates {
2125 gate.static_off();
2126 }
2127 }
2128
2129 fn name(&self) -> &str {
2130 "UCCSDLayer"
2131 }
2132
2133 fn zero_grad(&mut self) {
2134 for gate in &mut self.gates {
2135 gate.zero_grad();
2136 }
2137 }
2138}
2139
2140pub struct TQSymmetryPreservingLayer {
2145 n_wires: usize,
2146 n_blocks: usize,
2147 symmetry_type: SymmetryType,
2148 layers: Vec<Box<dyn TQModule>>,
2149 static_mode: bool,
2150}
2151
2152#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2154pub enum SymmetryType {
2155 ParticleNumber,
2157 SpinConservation,
2159 TimeReversal,
2161}
2162
2163impl TQSymmetryPreservingLayer {
2164 pub fn new(n_wires: usize, n_blocks: usize, symmetry_type: SymmetryType) -> Self {
2165 let layers = Self::build_layers(n_wires, n_blocks, symmetry_type);
2166
2167 Self {
2168 n_wires,
2169 n_blocks,
2170 symmetry_type,
2171 layers,
2172 static_mode: false,
2173 }
2174 }
2175
2176 fn build_layers(
2177 n_wires: usize,
2178 n_blocks: usize,
2179 symmetry_type: SymmetryType,
2180 ) -> Vec<Box<dyn TQModule>> {
2181 let mut layers: Vec<Box<dyn TQModule>> = Vec::new();
2182
2183 match symmetry_type {
2184 SymmetryType::ParticleNumber => {
2185 for _ in 0..n_blocks {
2187 layers.push(Box::new(TQExcitationPreservingLayer::new(
2188 n_wires, 1, false,
2189 )));
2190 }
2191 }
2192 SymmetryType::SpinConservation => {
2193 for _ in 0..n_blocks {
2195 layers.push(Box::new(TQOp1QAllLayer::rz(n_wires, true)));
2196 layers.push(Box::new(TQOp2QAllLayer::new(
2197 "rxx", n_wires, true, true, 1, false,
2198 )));
2199 layers.push(Box::new(TQOp2QAllLayer::new(
2200 "ryy", n_wires, true, true, 1, false,
2201 )));
2202 }
2203 }
2204 SymmetryType::TimeReversal => {
2205 for _ in 0..n_blocks {
2207 layers.push(Box::new(TQOp1QAllLayer::ry(n_wires, true)));
2208 layers.push(Box::new(TQOp2QAllLayer::cnot(n_wires, true)));
2209 }
2210 }
2211 }
2212
2213 layers
2214 }
2215
2216 pub fn particle_number(n_wires: usize, n_blocks: usize) -> Self {
2217 Self::new(n_wires, n_blocks, SymmetryType::ParticleNumber)
2218 }
2219
2220 pub fn spin_conserving(n_wires: usize, n_blocks: usize) -> Self {
2221 Self::new(n_wires, n_blocks, SymmetryType::SpinConservation)
2222 }
2223
2224 pub fn time_reversal(n_wires: usize, n_blocks: usize) -> Self {
2225 Self::new(n_wires, n_blocks, SymmetryType::TimeReversal)
2226 }
2227}
2228
2229impl TQModule for TQSymmetryPreservingLayer {
2230 fn forward(&mut self, qdev: &mut TQDevice) -> Result<()> {
2231 for layer in &mut self.layers {
2232 layer.forward(qdev)?;
2233 }
2234 Ok(())
2235 }
2236
2237 fn parameters(&self) -> Vec<TQParameter> {
2238 self.layers.iter().flat_map(|l| l.parameters()).collect()
2239 }
2240
2241 fn n_wires(&self) -> Option<usize> {
2242 Some(self.n_wires)
2243 }
2244
2245 fn set_n_wires(&mut self, n_wires: usize) {
2246 self.n_wires = n_wires;
2247 self.layers = Self::build_layers(n_wires, self.n_blocks, self.symmetry_type);
2248 }
2249
2250 fn is_static_mode(&self) -> bool {
2251 self.static_mode
2252 }
2253
2254 fn static_on(&mut self) {
2255 self.static_mode = true;
2256 for layer in &mut self.layers {
2257 layer.static_on();
2258 }
2259 }
2260
2261 fn static_off(&mut self) {
2262 self.static_mode = false;
2263 for layer in &mut self.layers {
2264 layer.static_off();
2265 }
2266 }
2267
2268 fn name(&self) -> &str {
2269 "SymmetryPreservingLayer"
2270 }
2271
2272 fn zero_grad(&mut self) {
2273 for layer in &mut self.layers {
2274 layer.zero_grad();
2275 }
2276 }
2277}