Skip to content

Commit ff81f80

Browse files
authored
Implement the inverse of IonQ native gates (#5889)
Implement the inverse of IonQ's native gates, GPIGate, GPI2Gate and MSGate, by implementing `__pow__` method for `power==-1`.
1 parent cfe1d8b commit ff81f80

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

cirq-ionq/cirq_ionq/ionq_native_gates.py

+27
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ def _circuit_diagram_info_(
7070
) -> Union[str, 'protocols.CircuitDiagramInfo']:
7171
return protocols.CircuitDiagramInfo(wire_symbols=(f'GPI({self.phase!r})',))
7272

73+
def __pow__(self, power):
74+
if power == 1:
75+
return self
76+
77+
if power == -1:
78+
return self
79+
80+
return NotImplemented
81+
7382

7483
GPI = GPIGate(phi=0)
7584
document(
@@ -137,6 +146,15 @@ def _json_dict_(self) -> Dict[str, Any]:
137146
def _value_equality_values_(self) -> Any:
138147
return self.phi
139148

149+
def __pow__(self, power):
150+
if power == 1:
151+
return self
152+
153+
if power == -1:
154+
return GPI2Gate(phi=self.phi + 0.5)
155+
156+
return NotImplemented
157+
140158

141159
GPI2 = GPI2Gate(phi=0)
142160
document(
@@ -219,6 +237,15 @@ def _json_dict_(self) -> Dict[str, Any]:
219237
def _value_equality_values_(self) -> Any:
220238
return (self.phi0, self.phi1)
221239

240+
def __pow__(self, power):
241+
if power == 1:
242+
return self
243+
244+
if power == -1:
245+
return MSGate(phi0=self.phi0 + 0.5, phi1=self.phi1)
246+
247+
return NotImplemented
248+
222249

223250
MS = MSGate(phi0=0, phi1=0)
224251
document(

cirq-ionq/cirq_ionq/ionq_native_gates_test.py

+59
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
import cirq_ionq as ionq
2222

2323

24+
PARAMS_FOR_ONE_ANGLE_GATE = [0, 0.1, 0.4, math.pi / 2, math.pi, 2 * math.pi]
25+
PARAMS_FOR_TWO_ANGLE_GATE = [
26+
(0, 1),
27+
(0.1, 1),
28+
(0.4, 1),
29+
(math.pi / 2, 0),
30+
(0, math.pi),
31+
(0.1, 2 * math.pi),
32+
]
33+
INVALID_GATE_POWER = [-2, -0.5, 0, 0.5, 2]
34+
35+
2436
@pytest.mark.parametrize(
2537
"gate,nqubits,diagram",
2638
[
@@ -74,3 +86,50 @@ def test_ms_unitary(phases):
7486

7587
mat = cirq.protocols.unitary(gate)
7688
numpy.testing.assert_array_almost_equal(mat.dot(mat.conj().T), numpy.identity(4))
89+
90+
91+
@pytest.mark.parametrize(
92+
"gate",
93+
[
94+
*[ionq.GPIGate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
95+
*[ionq.GPI2Gate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
96+
*[ionq.MSGate(phi0=angles[0], phi1=angles[1]) for angles in PARAMS_FOR_TWO_ANGLE_GATE],
97+
],
98+
)
99+
def test_gate_inverse(gate):
100+
"""Tests that the inverse of natives gate are correct."""
101+
mat = cirq.protocols.unitary(gate)
102+
mat_inverse = cirq.protocols.unitary(gate**-1)
103+
dim = mat.shape[0]
104+
105+
numpy.testing.assert_array_almost_equal(mat.dot(mat_inverse), numpy.identity(dim))
106+
107+
108+
@pytest.mark.parametrize(
109+
"gate",
110+
[
111+
*[ionq.GPIGate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
112+
*[ionq.GPI2Gate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
113+
*[ionq.MSGate(phi0=angles[0], phi1=angles[1]) for angles in PARAMS_FOR_TWO_ANGLE_GATE],
114+
],
115+
)
116+
def test_gate_power1(gate):
117+
"""Tests that power=1 for native gates are correct."""
118+
mat = cirq.protocols.unitary(gate)
119+
mat_power1 = cirq.protocols.unitary(gate**1)
120+
121+
numpy.testing.assert_array_almost_equal(mat, mat_power1)
122+
123+
124+
@pytest.mark.parametrize(
125+
"gate,power",
126+
[
127+
*[(ionq.GPIGate(phi=0.1), power) for power in INVALID_GATE_POWER],
128+
*[(ionq.GPI2Gate(phi=0.1), power) for power in INVALID_GATE_POWER],
129+
*[(ionq.MSGate(phi0=0.1, phi1=0.2), power) for power in INVALID_GATE_POWER],
130+
],
131+
)
132+
def test_gate_power_not_implemented(gate, power):
133+
"""Tests that any power other than 1 and -1 is not implemented."""
134+
with pytest.raises(TypeError):
135+
_ = gate**power

0 commit comments

Comments
 (0)