@@ -87,11 +87,19 @@ class XPowGate(eigen_gate.EigenGate):
87
87
`cirq.X`, the Pauli X gate, is an instance of this gate at `exponent=1`.
88
88
"""
89
89
90
+ _eigencomponents : Dict [int , List [Tuple [float , np .ndarray ]]] = {}
91
+
92
+ def __init__ (
93
+ self , * , exponent : value .TParamVal = 1.0 , global_shift : float = 0.0 , dimension : int = 2
94
+ ):
95
+ super ().__init__ (exponent = exponent , global_shift = global_shift )
96
+ self ._dimension = dimension
97
+
90
98
def _num_qubits_ (self ) -> int :
91
99
return 1
92
100
93
101
def _apply_unitary_ (self , args : 'protocols.ApplyUnitaryArgs' ) -> Optional [np .ndarray ]:
94
- if self ._exponent != 1 :
102
+ if self ._exponent != 1 or self . _dimension != 2 :
95
103
return NotImplemented
96
104
zero = args .subspace_index (0 )
97
105
one = args .subspace_index (1 )
@@ -108,10 +116,27 @@ def in_su2(self) -> 'Rx':
108
116
109
117
def with_canonical_global_phase (self ) -> 'XPowGate' :
110
118
"""Returns an equal-up-global-phase standardized form of the gate."""
111
- return XPowGate (exponent = self ._exponent )
119
+ return XPowGate (exponent = self ._exponent , dimension = self ._dimension )
120
+
121
+ def _qid_shape_ (self ) -> Tuple [int , ...]:
122
+ return (self ._dimension ,)
112
123
113
124
def _eigen_components (self ) -> List [Tuple [float , np .ndarray ]]:
114
- return [(0 , np .array ([[0.5 , 0.5 ], [0.5 , 0.5 ]])), (1 , np .array ([[0.5 , - 0.5 ], [- 0.5 , 0.5 ]]))]
125
+ if self ._dimension not in XPowGate ._eigencomponents :
126
+ components = []
127
+ root = 1j ** (4 / self ._dimension )
128
+ for i in range (self ._dimension ):
129
+ half_turns = i * 2 / self ._dimension
130
+ v = np .array ([root ** (i * j ) / self ._dimension for j in range (self ._dimension )])
131
+ m = np .array ([np .roll (v , j ) for j in range (self ._dimension )])
132
+ components .append ((half_turns , m ))
133
+ XPowGate ._eigencomponents [self ._dimension ] = components
134
+ return XPowGate ._eigencomponents [self ._dimension ]
135
+
136
+ def _with_exponent (self , exponent : 'cirq.TParamVal' ) -> 'cirq.XPowGate' :
137
+ return XPowGate (
138
+ exponent = exponent , global_shift = self ._global_shift , dimension = self ._dimension
139
+ )
115
140
116
141
def _decompose_into_clifford_with_qubits_ (self , qubits ):
117
142
from cirq .ops .clifford_gate import SingleQubitCliffordGate
@@ -127,7 +152,7 @@ def _decompose_into_clifford_with_qubits_(self, qubits):
127
152
return NotImplemented
128
153
129
154
def _trace_distance_bound_ (self ) -> Optional [float ]:
130
- if self ._is_parameterized_ ():
155
+ if self ._is_parameterized_ () or self . _dimension != 2 :
131
156
return None
132
157
return abs (np .sin (self ._exponent * 0.5 * np .pi ))
133
158
@@ -179,7 +204,7 @@ def controlled(
179
204
return result
180
205
181
206
def _pauli_expansion_ (self ) -> value .LinearDict [str ]:
182
- if protocols .is_parameterized (self ):
207
+ if protocols .is_parameterized (self ) or self . _dimension != 2 :
183
208
return NotImplemented
184
209
phase = 1j ** (2 * self ._exponent * (self ._global_shift + 0.5 ))
185
210
angle = np .pi * self ._exponent / 2
@@ -220,7 +245,7 @@ def _phase_by_(self, phase_turns, qubit_index):
220
245
)
221
246
222
247
def _has_stabilizer_effect_ (self ) -> Optional [bool ]:
223
- if self ._is_parameterized_ ():
248
+ if self ._is_parameterized_ () or self . _dimension != 2 :
224
249
return None
225
250
return self .exponent % 0.5 == 0
226
251
@@ -232,13 +257,19 @@ def __str__(self) -> str:
232
257
return f'XPowGate(exponent={ self ._exponent } , global_shift={ self ._global_shift !r} )'
233
258
234
259
def __repr__ (self ) -> str :
235
- if self ._global_shift == 0 :
260
+ if self ._global_shift == 0 and self . _dimension == 2 :
236
261
if self ._exponent == 1 :
237
262
return 'cirq.X'
238
263
return f'(cirq.X**{ proper_repr (self ._exponent )} )'
239
- return 'cirq.XPowGate(exponent={}, global_shift={!r})' .format (
240
- proper_repr (self ._exponent ), self ._global_shift
241
- )
264
+ args = []
265
+ if self ._exponent != 1 :
266
+ args .append (f'exponent={ proper_repr (self ._exponent )} ' )
267
+ if self ._global_shift != 0 :
268
+ args .append (f'global_shift={ self ._global_shift } ' )
269
+ if self ._dimension != 2 :
270
+ args .append (f'dimension={ self ._dimension } ' )
271
+ all_args = ', ' .join (args )
272
+ return f'cirq.XPowGate({ all_args } )'
242
273
243
274
244
275
class Rx (XPowGate ):
@@ -478,16 +509,25 @@ class ZPowGate(eigen_gate.EigenGate):
478
509
`cirq.Z`, the Pauli Z gate, is an instance of this gate at `exponent=1`.
479
510
"""
480
511
512
+ _eigencomponents : Dict [int , List [Tuple [float , np .ndarray ]]] = {}
513
+
514
+ def __init__ (
515
+ self , * , exponent : value .TParamVal = 1.0 , global_shift : float = 0.0 , dimension : int = 2
516
+ ):
517
+ super ().__init__ (exponent = exponent , global_shift = global_shift )
518
+ self ._dimension = dimension
519
+
481
520
def _num_qubits_ (self ) -> int :
482
521
return 1
483
522
484
523
def _apply_unitary_ (self , args : 'protocols.ApplyUnitaryArgs' ) -> Optional [np .ndarray ]:
485
524
if protocols .is_parameterized (self ):
486
525
return None
487
526
488
- one = args .subspace_index (1 )
489
- c = 1j ** (self ._exponent * 2 )
490
- args .target_tensor [one ] *= c
527
+ for i in range (1 , self ._dimension ):
528
+ subspace = args .subspace_index (i )
529
+ c = 1j ** (self ._exponent * 4 * i / self ._dimension )
530
+ args .target_tensor [subspace ] *= c
491
531
p = 1j ** (2 * self ._exponent * self ._global_shift )
492
532
if p != 1 :
493
533
args .target_tensor *= p
@@ -512,7 +552,7 @@ def in_su2(self) -> 'Rz':
512
552
513
553
def with_canonical_global_phase (self ) -> 'ZPowGate' :
514
554
"""Returns an equal-up-global-phase standardized form of the gate."""
515
- return ZPowGate (exponent = self ._exponent )
555
+ return ZPowGate (exponent = self ._exponent , dimension = self . _dimension )
516
556
517
557
def controlled (
518
558
self ,
@@ -561,16 +601,32 @@ def controlled(
561
601
)
562
602
return result
563
603
604
+ def _qid_shape_ (self ) -> Tuple [int , ...]:
605
+ return (self ._dimension ,)
606
+
564
607
def _eigen_components (self ) -> List [Tuple [float , np .ndarray ]]:
565
- return [(0 , np .diag ([1 , 0 ])), (1 , np .diag ([0 , 1 ]))]
608
+ if self ._dimension not in ZPowGate ._eigencomponents :
609
+ components = []
610
+ for i in range (self ._dimension ):
611
+ half_turns = i * 2 / self ._dimension
612
+ m = np .zeros ((self ._dimension , self ._dimension ))
613
+ m [i ][i ] = 1
614
+ components .append ((half_turns , m ))
615
+ ZPowGate ._eigencomponents [self ._dimension ] = components
616
+ return ZPowGate ._eigencomponents [self ._dimension ]
617
+
618
+ def _with_exponent (self , exponent : 'cirq.TParamVal' ) -> 'cirq.ZPowGate' :
619
+ return ZPowGate (
620
+ exponent = exponent , global_shift = self ._global_shift , dimension = self ._dimension
621
+ )
566
622
567
623
def _trace_distance_bound_ (self ) -> Optional [float ]:
568
- if self ._is_parameterized_ ():
624
+ if self ._is_parameterized_ () or self . _dimension != 2 :
569
625
return None
570
626
return abs (np .sin (self ._exponent * 0.5 * np .pi ))
571
627
572
628
def _pauli_expansion_ (self ) -> value .LinearDict [str ]:
573
- if protocols .is_parameterized (self ):
629
+ if protocols .is_parameterized (self ) or self . _dimension != 2 :
574
630
return NotImplemented
575
631
phase = 1j ** (2 * self ._exponent * (self ._global_shift + 0.5 ))
576
632
angle = np .pi * self ._exponent / 2
@@ -580,7 +636,7 @@ def _phase_by_(self, phase_turns: float, qubit_index: int):
580
636
return self
581
637
582
638
def _has_stabilizer_effect_ (self ) -> Optional [bool ]:
583
- if self ._is_parameterized_ ():
639
+ if self ._is_parameterized_ () or self . _dimension != 2 :
584
640
return None
585
641
return self .exponent % 0.5 == 0
586
642
@@ -630,7 +686,7 @@ def __str__(self) -> str:
630
686
return f'ZPowGate(exponent={ self ._exponent } , global_shift={ self ._global_shift !r} )'
631
687
632
688
def __repr__ (self ) -> str :
633
- if self ._global_shift == 0 :
689
+ if self ._global_shift == 0 and self . _dimension == 2 :
634
690
if self ._exponent == 0.25 :
635
691
return 'cirq.T'
636
692
if self ._exponent == - 0.25 :
@@ -642,9 +698,15 @@ def __repr__(self) -> str:
642
698
if self ._exponent == 1 :
643
699
return 'cirq.Z'
644
700
return f'(cirq.Z**{ proper_repr (self ._exponent )} )'
645
- return 'cirq.ZPowGate(exponent={}, global_shift={!r})' .format (
646
- proper_repr (self ._exponent ), self ._global_shift
647
- )
701
+ args = []
702
+ if self ._exponent != 1 :
703
+ args .append (f'exponent={ proper_repr (self ._exponent )} ' )
704
+ if self ._global_shift != 0 :
705
+ args .append (f'global_shift={ self ._global_shift } ' )
706
+ if self ._dimension != 2 :
707
+ args .append (f'dimension={ self ._dimension } ' )
708
+ all_args = ', ' .join (args )
709
+ return f'cirq.ZPowGate({ all_args } )'
648
710
649
711
def _commutes_on_qids_ (
650
712
self , qids : 'Sequence[cirq.Qid]' , other : Any , * , atol : float = 1e-8
0 commit comments