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