Skip to content

Commit

Permalink
Implement the inverse of IonQ native gates (#5889)
Browse files Browse the repository at this point in the history
Implement the inverse of IonQ's native gates, GPIGate, GPI2Gate and MSGate, by implementing `__pow__` method for `power==-1`.
  • Loading branch information
yitchen-tim committed Sep 28, 2022
1 parent cfe1d8b commit ff81f80
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
27 changes: 27 additions & 0 deletions cirq-ionq/cirq_ionq/ionq_native_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ def _circuit_diagram_info_(
) -> Union[str, 'protocols.CircuitDiagramInfo']:
return protocols.CircuitDiagramInfo(wire_symbols=(f'GPI({self.phase!r})',))

def __pow__(self, power):
if power == 1:
return self

if power == -1:
return self

return NotImplemented


GPI = GPIGate(phi=0)
document(
Expand Down Expand Up @@ -137,6 +146,15 @@ def _json_dict_(self) -> Dict[str, Any]:
def _value_equality_values_(self) -> Any:
return self.phi

def __pow__(self, power):
if power == 1:
return self

if power == -1:
return GPI2Gate(phi=self.phi + 0.5)

return NotImplemented


GPI2 = GPI2Gate(phi=0)
document(
Expand Down Expand Up @@ -219,6 +237,15 @@ def _json_dict_(self) -> Dict[str, Any]:
def _value_equality_values_(self) -> Any:
return (self.phi0, self.phi1)

def __pow__(self, power):
if power == 1:
return self

if power == -1:
return MSGate(phi0=self.phi0 + 0.5, phi1=self.phi1)

return NotImplemented


MS = MSGate(phi0=0, phi1=0)
document(
Expand Down
59 changes: 59 additions & 0 deletions cirq-ionq/cirq_ionq/ionq_native_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@
import cirq_ionq as ionq


PARAMS_FOR_ONE_ANGLE_GATE = [0, 0.1, 0.4, math.pi / 2, math.pi, 2 * math.pi]
PARAMS_FOR_TWO_ANGLE_GATE = [
(0, 1),
(0.1, 1),
(0.4, 1),
(math.pi / 2, 0),
(0, math.pi),
(0.1, 2 * math.pi),
]
INVALID_GATE_POWER = [-2, -0.5, 0, 0.5, 2]


@pytest.mark.parametrize(
"gate,nqubits,diagram",
[
Expand Down Expand Up @@ -74,3 +86,50 @@ def test_ms_unitary(phases):

mat = cirq.protocols.unitary(gate)
numpy.testing.assert_array_almost_equal(mat.dot(mat.conj().T), numpy.identity(4))


@pytest.mark.parametrize(
"gate",
[
*[ionq.GPIGate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
*[ionq.GPI2Gate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
*[ionq.MSGate(phi0=angles[0], phi1=angles[1]) for angles in PARAMS_FOR_TWO_ANGLE_GATE],
],
)
def test_gate_inverse(gate):
"""Tests that the inverse of natives gate are correct."""
mat = cirq.protocols.unitary(gate)
mat_inverse = cirq.protocols.unitary(gate**-1)
dim = mat.shape[0]

numpy.testing.assert_array_almost_equal(mat.dot(mat_inverse), numpy.identity(dim))


@pytest.mark.parametrize(
"gate",
[
*[ionq.GPIGate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
*[ionq.GPI2Gate(phi=angle) for angle in PARAMS_FOR_ONE_ANGLE_GATE],
*[ionq.MSGate(phi0=angles[0], phi1=angles[1]) for angles in PARAMS_FOR_TWO_ANGLE_GATE],
],
)
def test_gate_power1(gate):
"""Tests that power=1 for native gates are correct."""
mat = cirq.protocols.unitary(gate)
mat_power1 = cirq.protocols.unitary(gate**1)

numpy.testing.assert_array_almost_equal(mat, mat_power1)


@pytest.mark.parametrize(
"gate,power",
[
*[(ionq.GPIGate(phi=0.1), power) for power in INVALID_GATE_POWER],
*[(ionq.GPI2Gate(phi=0.1), power) for power in INVALID_GATE_POWER],
*[(ionq.MSGate(phi0=0.1, phi1=0.2), power) for power in INVALID_GATE_POWER],
],
)
def test_gate_power_not_implemented(gate, power):
"""Tests that any power other than 1 and -1 is not implemented."""
with pytest.raises(TypeError):
_ = gate**power

0 comments on commit ff81f80

Please sign in to comment.