quantrs2_core/
gate.rs

1use num_complex::Complex64;
2use std::any::Any;
3use std::f64::consts::PI;
4use std::fmt::Debug;
5
6use crate::error::QuantRS2Result;
7use crate::qubit::QubitId;
8
9/// Trait for quantum gate operations
10pub trait GateOp: Debug + Send + Sync {
11    /// Returns the name of the gate
12    fn name(&self) -> &'static str;
13
14    /// Returns the qubits that this gate acts on
15    fn qubits(&self) -> Vec<QubitId>;
16
17    /// Returns the number of qubits this gate acts on
18    fn num_qubits(&self) -> usize {
19        self.qubits().len()
20    }
21
22    /// Returns true if this gate is parameterized
23    fn is_parameterized(&self) -> bool {
24        false
25    }
26
27    /// Returns the matrix representation of this gate
28    fn matrix(&self) -> QuantRS2Result<Vec<Complex64>>;
29
30    /// Downcast to concrete gate type
31    fn as_any(&self) -> &dyn Any;
32}
33
34/// Single-qubit gate operations
35pub mod single {
36    use super::*;
37    use std::any::Any;
38
39    /// Hadamard gate
40    #[derive(Debug, Clone, Copy)]
41    pub struct Hadamard {
42        /// Target qubit
43        pub target: QubitId,
44    }
45
46    impl GateOp for Hadamard {
47        fn name(&self) -> &'static str {
48            "H"
49        }
50
51        fn qubits(&self) -> Vec<QubitId> {
52            vec![self.target]
53        }
54
55        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
56            let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
57            Ok(vec![
58                Complex64::new(sqrt2_inv, 0.0),
59                Complex64::new(sqrt2_inv, 0.0),
60                Complex64::new(sqrt2_inv, 0.0),
61                Complex64::new(-sqrt2_inv, 0.0),
62            ])
63        }
64
65        fn as_any(&self) -> &dyn Any {
66            self
67        }
68    }
69
70    /// Pauli-X gate
71    #[derive(Debug, Clone, Copy)]
72    pub struct PauliX {
73        /// Target qubit
74        pub target: QubitId,
75    }
76
77    impl GateOp for PauliX {
78        fn name(&self) -> &'static str {
79            "X"
80        }
81
82        fn qubits(&self) -> Vec<QubitId> {
83            vec![self.target]
84        }
85
86        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
87            Ok(vec![
88                Complex64::new(0.0, 0.0),
89                Complex64::new(1.0, 0.0),
90                Complex64::new(1.0, 0.0),
91                Complex64::new(0.0, 0.0),
92            ])
93        }
94
95        fn as_any(&self) -> &dyn Any {
96            self
97        }
98    }
99
100    /// Pauli-Y gate
101    #[derive(Debug, Clone, Copy)]
102    pub struct PauliY {
103        /// Target qubit
104        pub target: QubitId,
105    }
106
107    impl GateOp for PauliY {
108        fn name(&self) -> &'static str {
109            "Y"
110        }
111
112        fn qubits(&self) -> Vec<QubitId> {
113            vec![self.target]
114        }
115
116        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
117            Ok(vec![
118                Complex64::new(0.0, 0.0),
119                Complex64::new(0.0, -1.0),
120                Complex64::new(0.0, 1.0),
121                Complex64::new(0.0, 0.0),
122            ])
123        }
124
125        fn as_any(&self) -> &dyn Any {
126            self
127        }
128    }
129
130    /// Pauli-Z gate
131    #[derive(Debug, Clone, Copy)]
132    pub struct PauliZ {
133        /// Target qubit
134        pub target: QubitId,
135    }
136
137    impl GateOp for PauliZ {
138        fn name(&self) -> &'static str {
139            "Z"
140        }
141
142        fn qubits(&self) -> Vec<QubitId> {
143            vec![self.target]
144        }
145
146        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
147            Ok(vec![
148                Complex64::new(1.0, 0.0),
149                Complex64::new(0.0, 0.0),
150                Complex64::new(0.0, 0.0),
151                Complex64::new(-1.0, 0.0),
152            ])
153        }
154
155        fn as_any(&self) -> &dyn Any {
156            self
157        }
158    }
159
160    /// Rotation around X-axis
161    #[derive(Debug, Clone, Copy)]
162    pub struct RotationX {
163        /// Target qubit
164        pub target: QubitId,
165
166        /// Rotation angle (in radians)
167        pub theta: f64,
168    }
169
170    impl GateOp for RotationX {
171        fn name(&self) -> &'static str {
172            "RX"
173        }
174
175        fn qubits(&self) -> Vec<QubitId> {
176            vec![self.target]
177        }
178
179        fn is_parameterized(&self) -> bool {
180            true
181        }
182
183        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
184            let cos = (self.theta / 2.0).cos();
185            let sin = (self.theta / 2.0).sin();
186            Ok(vec![
187                Complex64::new(cos, 0.0),
188                Complex64::new(0.0, -sin),
189                Complex64::new(0.0, -sin),
190                Complex64::new(cos, 0.0),
191            ])
192        }
193
194        fn as_any(&self) -> &dyn Any {
195            self
196        }
197    }
198
199    /// Rotation around Y-axis
200    #[derive(Debug, Clone, Copy)]
201    pub struct RotationY {
202        /// Target qubit
203        pub target: QubitId,
204
205        /// Rotation angle (in radians)
206        pub theta: f64,
207    }
208
209    impl GateOp for RotationY {
210        fn name(&self) -> &'static str {
211            "RY"
212        }
213
214        fn qubits(&self) -> Vec<QubitId> {
215            vec![self.target]
216        }
217
218        fn is_parameterized(&self) -> bool {
219            true
220        }
221
222        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
223            let cos = (self.theta / 2.0).cos();
224            let sin = (self.theta / 2.0).sin();
225            Ok(vec![
226                Complex64::new(cos, 0.0),
227                Complex64::new(-sin, 0.0),
228                Complex64::new(sin, 0.0),
229                Complex64::new(cos, 0.0),
230            ])
231        }
232
233        fn as_any(&self) -> &dyn Any {
234            self
235        }
236    }
237
238    /// Rotation around Z-axis
239    #[derive(Debug, Clone, Copy)]
240    pub struct RotationZ {
241        /// Target qubit
242        pub target: QubitId,
243
244        /// Rotation angle (in radians)
245        pub theta: f64,
246    }
247
248    impl GateOp for RotationZ {
249        fn name(&self) -> &'static str {
250            "RZ"
251        }
252
253        fn qubits(&self) -> Vec<QubitId> {
254            vec![self.target]
255        }
256
257        fn is_parameterized(&self) -> bool {
258            true
259        }
260
261        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
262            let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
263            let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
264            Ok(vec![
265                phase_conj,
266                Complex64::new(0.0, 0.0),
267                Complex64::new(0.0, 0.0),
268                phase,
269            ])
270        }
271
272        fn as_any(&self) -> &dyn Any {
273            self
274        }
275    }
276
277    /// Phase gate (S gate)
278    #[derive(Debug, Clone, Copy)]
279    pub struct Phase {
280        /// Target qubit
281        pub target: QubitId,
282    }
283
284    impl GateOp for Phase {
285        fn name(&self) -> &'static str {
286            "S"
287        }
288
289        fn qubits(&self) -> Vec<QubitId> {
290            vec![self.target]
291        }
292
293        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
294            Ok(vec![
295                Complex64::new(1.0, 0.0),
296                Complex64::new(0.0, 0.0),
297                Complex64::new(0.0, 0.0),
298                Complex64::new(0.0, 1.0),
299            ])
300        }
301
302        fn as_any(&self) -> &dyn Any {
303            self
304        }
305    }
306
307    /// T gate
308    #[derive(Debug, Clone, Copy)]
309    pub struct T {
310        /// Target qubit
311        pub target: QubitId,
312    }
313
314    impl GateOp for T {
315        fn name(&self) -> &'static str {
316            "T"
317        }
318
319        fn qubits(&self) -> Vec<QubitId> {
320            vec![self.target]
321        }
322
323        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
324            let phase = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
325            Ok(vec![
326                Complex64::new(1.0, 0.0),
327                Complex64::new(0.0, 0.0),
328                Complex64::new(0.0, 0.0),
329                phase,
330            ])
331        }
332
333        fn as_any(&self) -> &dyn Any {
334            self
335        }
336    }
337
338    /// T-dagger gate (Conjugate of T gate)
339    #[derive(Debug, Clone, Copy)]
340    pub struct TDagger {
341        /// Target qubit
342        pub target: QubitId,
343    }
344
345    impl GateOp for TDagger {
346        fn name(&self) -> &'static str {
347            "T†"
348        }
349
350        fn qubits(&self) -> Vec<QubitId> {
351            vec![self.target]
352        }
353
354        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
355            let phase = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
356            Ok(vec![
357                Complex64::new(1.0, 0.0),
358                Complex64::new(0.0, 0.0),
359                Complex64::new(0.0, 0.0),
360                phase,
361            ])
362        }
363
364        fn as_any(&self) -> &dyn Any {
365            self
366        }
367    }
368
369    /// S-dagger gate (Conjugate of Phase/S gate)
370    #[derive(Debug, Clone, Copy)]
371    pub struct PhaseDagger {
372        /// Target qubit
373        pub target: QubitId,
374    }
375
376    impl GateOp for PhaseDagger {
377        fn name(&self) -> &'static str {
378            "S†"
379        }
380
381        fn qubits(&self) -> Vec<QubitId> {
382            vec![self.target]
383        }
384
385        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
386            Ok(vec![
387                Complex64::new(1.0, 0.0),
388                Complex64::new(0.0, 0.0),
389                Complex64::new(0.0, 0.0),
390                Complex64::new(0.0, -1.0),
391            ])
392        }
393
394        fn as_any(&self) -> &dyn Any {
395            self
396        }
397    }
398
399    /// Square Root of X (√X) gate
400    #[derive(Debug, Clone, Copy)]
401    pub struct SqrtX {
402        /// Target qubit
403        pub target: QubitId,
404    }
405
406    impl GateOp for SqrtX {
407        fn name(&self) -> &'static str {
408            "√X"
409        }
410
411        fn qubits(&self) -> Vec<QubitId> {
412            vec![self.target]
413        }
414
415        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
416            // √X = [[0.5+0.5i, 0.5-0.5i], [0.5-0.5i, 0.5+0.5i]]
417            let half_plus_i_half = Complex64::new(0.5, 0.5);
418            let half_minus_i_half = Complex64::new(0.5, -0.5);
419
420            Ok(vec![
421                half_plus_i_half,
422                half_minus_i_half,
423                half_minus_i_half,
424                half_plus_i_half,
425            ])
426        }
427
428        fn as_any(&self) -> &dyn Any {
429            self
430        }
431    }
432
433    /// Square Root of X Dagger (√X†) gate
434    #[derive(Debug, Clone, Copy)]
435    pub struct SqrtXDagger {
436        /// Target qubit
437        pub target: QubitId,
438    }
439
440    impl GateOp for SqrtXDagger {
441        fn name(&self) -> &'static str {
442            "√X†"
443        }
444
445        fn qubits(&self) -> Vec<QubitId> {
446            vec![self.target]
447        }
448
449        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
450            // √X† = [[0.5-0.5i, 0.5+0.5i], [0.5+0.5i, 0.5-0.5i]]
451            let half_minus_i_half = Complex64::new(0.5, -0.5);
452            let half_plus_i_half = Complex64::new(0.5, 0.5);
453
454            Ok(vec![
455                half_minus_i_half,
456                half_plus_i_half,
457                half_plus_i_half,
458                half_minus_i_half,
459            ])
460        }
461
462        fn as_any(&self) -> &dyn Any {
463            self
464        }
465    }
466}
467
468/// Multi-qubit gate operations
469pub mod multi {
470    use super::*;
471    use std::any::Any;
472
473    /// Controlled-NOT gate
474    #[derive(Debug, Clone, Copy)]
475    pub struct CNOT {
476        /// Control qubit
477        pub control: QubitId,
478
479        /// Target qubit
480        pub target: QubitId,
481    }
482
483    impl GateOp for CNOT {
484        fn name(&self) -> &'static str {
485            "CNOT"
486        }
487
488        fn qubits(&self) -> Vec<QubitId> {
489            vec![self.control, self.target]
490        }
491
492        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
493            // For a 2-qubit gate, we return a 4x4 matrix in row-major order
494            Ok(vec![
495                Complex64::new(1.0, 0.0),
496                Complex64::new(0.0, 0.0),
497                Complex64::new(0.0, 0.0),
498                Complex64::new(0.0, 0.0),
499                Complex64::new(0.0, 0.0),
500                Complex64::new(1.0, 0.0),
501                Complex64::new(0.0, 0.0),
502                Complex64::new(0.0, 0.0),
503                Complex64::new(0.0, 0.0),
504                Complex64::new(0.0, 0.0),
505                Complex64::new(0.0, 0.0),
506                Complex64::new(1.0, 0.0),
507                Complex64::new(0.0, 0.0),
508                Complex64::new(0.0, 0.0),
509                Complex64::new(1.0, 0.0),
510                Complex64::new(0.0, 0.0),
511            ])
512        }
513
514        fn as_any(&self) -> &dyn Any {
515            self
516        }
517    }
518
519    /// Controlled-Z gate
520    #[derive(Debug, Clone, Copy)]
521    pub struct CZ {
522        /// Control qubit
523        pub control: QubitId,
524
525        /// Target qubit
526        pub target: QubitId,
527    }
528
529    impl GateOp for CZ {
530        fn name(&self) -> &'static str {
531            "CZ"
532        }
533
534        fn qubits(&self) -> Vec<QubitId> {
535            vec![self.control, self.target]
536        }
537
538        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
539            // For a 2-qubit gate, we return a 4x4 matrix in row-major order
540            Ok(vec![
541                Complex64::new(1.0, 0.0),
542                Complex64::new(0.0, 0.0),
543                Complex64::new(0.0, 0.0),
544                Complex64::new(0.0, 0.0),
545                Complex64::new(0.0, 0.0),
546                Complex64::new(1.0, 0.0),
547                Complex64::new(0.0, 0.0),
548                Complex64::new(0.0, 0.0),
549                Complex64::new(0.0, 0.0),
550                Complex64::new(0.0, 0.0),
551                Complex64::new(1.0, 0.0),
552                Complex64::new(0.0, 0.0),
553                Complex64::new(0.0, 0.0),
554                Complex64::new(0.0, 0.0),
555                Complex64::new(0.0, 0.0),
556                Complex64::new(-1.0, 0.0),
557            ])
558        }
559
560        fn as_any(&self) -> &dyn Any {
561            self
562        }
563    }
564
565    /// SWAP gate
566    #[derive(Debug, Clone, Copy)]
567    pub struct SWAP {
568        /// First qubit
569        pub qubit1: QubitId,
570
571        /// Second qubit
572        pub qubit2: QubitId,
573    }
574
575    impl GateOp for SWAP {
576        fn name(&self) -> &'static str {
577            "SWAP"
578        }
579
580        fn qubits(&self) -> Vec<QubitId> {
581            vec![self.qubit1, self.qubit2]
582        }
583
584        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
585            // For a 2-qubit gate, we return a 4x4 matrix in row-major order
586            Ok(vec![
587                Complex64::new(1.0, 0.0),
588                Complex64::new(0.0, 0.0),
589                Complex64::new(0.0, 0.0),
590                Complex64::new(0.0, 0.0),
591                Complex64::new(0.0, 0.0),
592                Complex64::new(0.0, 0.0),
593                Complex64::new(1.0, 0.0),
594                Complex64::new(0.0, 0.0),
595                Complex64::new(0.0, 0.0),
596                Complex64::new(1.0, 0.0),
597                Complex64::new(0.0, 0.0),
598                Complex64::new(0.0, 0.0),
599                Complex64::new(0.0, 0.0),
600                Complex64::new(0.0, 0.0),
601                Complex64::new(0.0, 0.0),
602                Complex64::new(1.0, 0.0),
603            ])
604        }
605
606        fn as_any(&self) -> &dyn Any {
607            self
608        }
609    }
610
611    /// Controlled-Y (CY) gate
612    #[derive(Debug, Clone, Copy)]
613    pub struct CY {
614        /// Control qubit
615        pub control: QubitId,
616
617        /// Target qubit
618        pub target: QubitId,
619    }
620
621    impl GateOp for CY {
622        fn name(&self) -> &'static str {
623            "CY"
624        }
625
626        fn qubits(&self) -> Vec<QubitId> {
627            vec![self.control, self.target]
628        }
629
630        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
631            // Matrix for CY:
632            // [[1, 0, 0, 0],
633            //  [0, 1, 0, 0],
634            //  [0, 0, 0, -i],
635            //  [0, 0, i, 0]]
636            Ok(vec![
637                Complex64::new(1.0, 0.0),  // (0,0)
638                Complex64::new(0.0, 0.0),  // (0,1)
639                Complex64::new(0.0, 0.0),  // (0,2)
640                Complex64::new(0.0, 0.0),  // (0,3)
641                Complex64::new(0.0, 0.0),  // (1,0)
642                Complex64::new(1.0, 0.0),  // (1,1)
643                Complex64::new(0.0, 0.0),  // (1,2)
644                Complex64::new(0.0, 0.0),  // (1,3)
645                Complex64::new(0.0, 0.0),  // (2,0)
646                Complex64::new(0.0, 0.0),  // (2,1)
647                Complex64::new(0.0, 0.0),  // (2,2)
648                Complex64::new(0.0, -1.0), // (2,3)
649                Complex64::new(0.0, 0.0),  // (3,0)
650                Complex64::new(0.0, 0.0),  // (3,1)
651                Complex64::new(0.0, 1.0),  // (3,2)
652                Complex64::new(0.0, 0.0),  // (3,3)
653            ])
654        }
655
656        fn as_any(&self) -> &dyn Any {
657            self
658        }
659    }
660
661    /// Controlled-H (CH) gate
662    #[derive(Debug, Clone, Copy)]
663    pub struct CH {
664        /// Control qubit
665        pub control: QubitId,
666
667        /// Target qubit
668        pub target: QubitId,
669    }
670
671    impl GateOp for CH {
672        fn name(&self) -> &'static str {
673            "CH"
674        }
675
676        fn qubits(&self) -> Vec<QubitId> {
677            vec![self.control, self.target]
678        }
679
680        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
681            // For a controlled-H gate, the matrix is:
682            // [[1, 0, 0, 0],
683            //  [0, 1, 0, 0],
684            //  [0, 0, 1/√2, 1/√2],
685            //  [0, 0, 1/√2, -1/√2]]
686            let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
687
688            Ok(vec![
689                Complex64::new(1.0, 0.0),        // (0,0)
690                Complex64::new(0.0, 0.0),        // (0,1)
691                Complex64::new(0.0, 0.0),        // (0,2)
692                Complex64::new(0.0, 0.0),        // (0,3)
693                Complex64::new(0.0, 0.0),        // (1,0)
694                Complex64::new(1.0, 0.0),        // (1,1)
695                Complex64::new(0.0, 0.0),        // (1,2)
696                Complex64::new(0.0, 0.0),        // (1,3)
697                Complex64::new(0.0, 0.0),        // (2,0)
698                Complex64::new(0.0, 0.0),        // (2,1)
699                Complex64::new(sqrt2_inv, 0.0),  // (2,2)
700                Complex64::new(sqrt2_inv, 0.0),  // (2,3)
701                Complex64::new(0.0, 0.0),        // (3,0)
702                Complex64::new(0.0, 0.0),        // (3,1)
703                Complex64::new(sqrt2_inv, 0.0),  // (3,2)
704                Complex64::new(-sqrt2_inv, 0.0), // (3,3)
705            ])
706        }
707
708        fn as_any(&self) -> &dyn Any {
709            self
710        }
711    }
712
713    /// Controlled-Phase (CS) gate
714    #[derive(Debug, Clone, Copy)]
715    pub struct CS {
716        /// Control qubit
717        pub control: QubitId,
718
719        /// Target qubit
720        pub target: QubitId,
721    }
722
723    impl GateOp for CS {
724        fn name(&self) -> &'static str {
725            "CS"
726        }
727
728        fn qubits(&self) -> Vec<QubitId> {
729            vec![self.control, self.target]
730        }
731
732        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
733            // For a controlled-S gate, the matrix is:
734            // [[1, 0, 0, 0],
735            //  [0, 1, 0, 0],
736            //  [0, 0, 1, 0],
737            //  [0, 0, 0, i]]
738            Ok(vec![
739                Complex64::new(1.0, 0.0), // (0,0)
740                Complex64::new(0.0, 0.0), // (0,1)
741                Complex64::new(0.0, 0.0), // (0,2)
742                Complex64::new(0.0, 0.0), // (0,3)
743                Complex64::new(0.0, 0.0), // (1,0)
744                Complex64::new(1.0, 0.0), // (1,1)
745                Complex64::new(0.0, 0.0), // (1,2)
746                Complex64::new(0.0, 0.0), // (1,3)
747                Complex64::new(0.0, 0.0), // (2,0)
748                Complex64::new(0.0, 0.0), // (2,1)
749                Complex64::new(1.0, 0.0), // (2,2)
750                Complex64::new(0.0, 0.0), // (2,3)
751                Complex64::new(0.0, 0.0), // (3,0)
752                Complex64::new(0.0, 0.0), // (3,1)
753                Complex64::new(0.0, 0.0), // (3,2)
754                Complex64::new(0.0, 1.0), // (3,3)
755            ])
756        }
757
758        fn as_any(&self) -> &dyn Any {
759            self
760        }
761    }
762
763    /// Toffoli (CCNOT) gate
764    #[derive(Debug, Clone, Copy)]
765    pub struct Toffoli {
766        /// First control qubit
767        pub control1: QubitId,
768
769        /// Second control qubit
770        pub control2: QubitId,
771
772        /// Target qubit
773        pub target: QubitId,
774    }
775
776    impl GateOp for Toffoli {
777        fn name(&self) -> &'static str {
778            "Toffoli"
779        }
780
781        fn qubits(&self) -> Vec<QubitId> {
782            vec![self.control1, self.control2, self.target]
783        }
784
785        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
786            // For a 3-qubit gate, we return an 8x8 matrix
787            // This would be very large to write out fully, so for now we return
788            // an error indicating it should be expanded into its constituent gates
789            Err(crate::error::QuantRS2Error::UnsupportedOperation(
790                "Direct matrix representation of Toffoli gate not supported. \
791                 Use gate decomposition."
792                    .into(),
793            ))
794        }
795
796        fn as_any(&self) -> &dyn Any {
797            self
798        }
799    }
800
801    /// Fredkin (CSWAP) gate
802    #[derive(Debug, Clone, Copy)]
803    pub struct Fredkin {
804        /// Control qubit
805        pub control: QubitId,
806
807        /// First target qubit
808        pub target1: QubitId,
809
810        /// Second target qubit
811        pub target2: QubitId,
812    }
813
814    impl GateOp for Fredkin {
815        fn name(&self) -> &'static str {
816            "Fredkin"
817        }
818
819        fn qubits(&self) -> Vec<QubitId> {
820            vec![self.control, self.target1, self.target2]
821        }
822
823        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
824            // For a 3-qubit gate, we return an 8x8 matrix
825            // This would be very large to write out fully, so for now we return
826            // an error indicating it should be expanded into its constituent gates
827            Err(crate::error::QuantRS2Error::UnsupportedOperation(
828                "Direct matrix representation of Fredkin gate not supported. \
829                 Use gate decomposition."
830                    .into(),
831            ))
832        }
833
834        fn as_any(&self) -> &dyn Any {
835            self
836        }
837    }
838
839    /// Controlled Rotation-X gate (CRX)
840    #[derive(Debug, Clone, Copy)]
841    pub struct CRX {
842        /// Control qubit
843        pub control: QubitId,
844
845        /// Target qubit
846        pub target: QubitId,
847
848        /// Rotation angle (in radians)
849        pub theta: f64,
850    }
851
852    impl GateOp for CRX {
853        fn name(&self) -> &'static str {
854            "CRX"
855        }
856
857        fn qubits(&self) -> Vec<QubitId> {
858            vec![self.control, self.target]
859        }
860
861        fn is_parameterized(&self) -> bool {
862            true
863        }
864
865        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
866            // For a controlled-RX gate, the matrix is:
867            // [[1, 0, 0, 0],
868            //  [0, 1, 0, 0],
869            //  [0, 0, cos(θ/2), -i·sin(θ/2)],
870            //  [0, 0, -i·sin(θ/2), cos(θ/2)]]
871            let cos = (self.theta / 2.0).cos();
872            let sin = (self.theta / 2.0).sin();
873
874            Ok(vec![
875                Complex64::new(1.0, 0.0),  // (0,0)
876                Complex64::new(0.0, 0.0),  // (0,1)
877                Complex64::new(0.0, 0.0),  // (0,2)
878                Complex64::new(0.0, 0.0),  // (0,3)
879                Complex64::new(0.0, 0.0),  // (1,0)
880                Complex64::new(1.0, 0.0),  // (1,1)
881                Complex64::new(0.0, 0.0),  // (1,2)
882                Complex64::new(0.0, 0.0),  // (1,3)
883                Complex64::new(0.0, 0.0),  // (2,0)
884                Complex64::new(0.0, 0.0),  // (2,1)
885                Complex64::new(cos, 0.0),  // (2,2)
886                Complex64::new(0.0, -sin), // (2,3)
887                Complex64::new(0.0, 0.0),  // (3,0)
888                Complex64::new(0.0, 0.0),  // (3,1)
889                Complex64::new(0.0, -sin), // (3,2)
890                Complex64::new(cos, 0.0),  // (3,3)
891            ])
892        }
893
894        fn as_any(&self) -> &dyn Any {
895            self
896        }
897    }
898
899    /// Controlled Rotation-Y gate (CRY)
900    #[derive(Debug, Clone, Copy)]
901    pub struct CRY {
902        /// Control qubit
903        pub control: QubitId,
904
905        /// Target qubit
906        pub target: QubitId,
907
908        /// Rotation angle (in radians)
909        pub theta: f64,
910    }
911
912    impl GateOp for CRY {
913        fn name(&self) -> &'static str {
914            "CRY"
915        }
916
917        fn qubits(&self) -> Vec<QubitId> {
918            vec![self.control, self.target]
919        }
920
921        fn is_parameterized(&self) -> bool {
922            true
923        }
924
925        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
926            // For a controlled-RY gate, the matrix is:
927            // [[1, 0, 0, 0],
928            //  [0, 1, 0, 0],
929            //  [0, 0, cos(θ/2), -sin(θ/2)],
930            //  [0, 0, sin(θ/2), cos(θ/2)]]
931            let cos = (self.theta / 2.0).cos();
932            let sin = (self.theta / 2.0).sin();
933
934            Ok(vec![
935                Complex64::new(1.0, 0.0),  // (0,0)
936                Complex64::new(0.0, 0.0),  // (0,1)
937                Complex64::new(0.0, 0.0),  // (0,2)
938                Complex64::new(0.0, 0.0),  // (0,3)
939                Complex64::new(0.0, 0.0),  // (1,0)
940                Complex64::new(1.0, 0.0),  // (1,1)
941                Complex64::new(0.0, 0.0),  // (1,2)
942                Complex64::new(0.0, 0.0),  // (1,3)
943                Complex64::new(0.0, 0.0),  // (2,0)
944                Complex64::new(0.0, 0.0),  // (2,1)
945                Complex64::new(cos, 0.0),  // (2,2)
946                Complex64::new(-sin, 0.0), // (2,3)
947                Complex64::new(0.0, 0.0),  // (3,0)
948                Complex64::new(0.0, 0.0),  // (3,1)
949                Complex64::new(sin, 0.0),  // (3,2)
950                Complex64::new(cos, 0.0),  // (3,3)
951            ])
952        }
953
954        fn as_any(&self) -> &dyn Any {
955            self
956        }
957    }
958
959    /// Controlled Rotation-Z gate (CRZ)
960    #[derive(Debug, Clone, Copy)]
961    pub struct CRZ {
962        /// Control qubit
963        pub control: QubitId,
964
965        /// Target qubit
966        pub target: QubitId,
967
968        /// Rotation angle (in radians)
969        pub theta: f64,
970    }
971
972    impl GateOp for CRZ {
973        fn name(&self) -> &'static str {
974            "CRZ"
975        }
976
977        fn qubits(&self) -> Vec<QubitId> {
978            vec![self.control, self.target]
979        }
980
981        fn is_parameterized(&self) -> bool {
982            true
983        }
984
985        fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
986            // For a controlled-RZ gate, the matrix is:
987            // [[1, 0, 0, 0],
988            //  [0, 1, 0, 0],
989            //  [0, 0, e^(-iθ/2), 0],
990            //  [0, 0, 0, e^(iθ/2)]]
991            let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
992            let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
993
994            Ok(vec![
995                Complex64::new(1.0, 0.0), // (0,0)
996                Complex64::new(0.0, 0.0), // (0,1)
997                Complex64::new(0.0, 0.0), // (0,2)
998                Complex64::new(0.0, 0.0), // (0,3)
999                Complex64::new(0.0, 0.0), // (1,0)
1000                Complex64::new(1.0, 0.0), // (1,1)
1001                Complex64::new(0.0, 0.0), // (1,2)
1002                Complex64::new(0.0, 0.0), // (1,3)
1003                Complex64::new(0.0, 0.0), // (2,0)
1004                Complex64::new(0.0, 0.0), // (2,1)
1005                phase_conj,               // (2,2)
1006                Complex64::new(0.0, 0.0), // (2,3)
1007                Complex64::new(0.0, 0.0), // (3,0)
1008                Complex64::new(0.0, 0.0), // (3,1)
1009                Complex64::new(0.0, 0.0), // (3,2)
1010                phase,                    // (3,3)
1011            ])
1012        }
1013
1014        fn as_any(&self) -> &dyn Any {
1015            self
1016        }
1017    }
1018}