Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass PauliEvolution gates to API #164

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -423,4 +423,4 @@ analyse-fallback-blocks=no

# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception
overgeneral-exceptions=builtins.Exception
26 changes: 25 additions & 1 deletion qiskit_ionq/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"x",
"y",
"z",
"PauliEvolution",
]

ionq_api_aliases = { # todo fix alias bug
Expand All @@ -100,6 +101,7 @@
"mcx_gray": "cx", # just one C for all mcx
"tdg": "ti",
"p": "z",
"PauliEvolution": "pauliexp",
"rxx": "xx",
"ryy": "yy",
"rzz": "zz",
Expand Down Expand Up @@ -189,6 +191,9 @@ def qiskit_circ_to_ionq_circ(input_circuit, gateset="qis"):
instruction.params[0]
)
}
if instruction_name == "PauliEvolution":
# rename rotation to time
rotation["time"] = rotation.pop("rotation")
elif instruction_name in {"zz"}:
rotation = {"angle": instruction.params[0]}
else:
Expand Down Expand Up @@ -253,6 +258,25 @@ def qiskit_circ_to_ionq_circ(input_circuit, gateset="qis"):
}
)

if instruction_name == "pauliexp":
assert set([coeff.imag for coeff in instruction.operator.coeffs]) == {0}, (
"PauliEvolution gate must have real coefficients, "
f"but got {set([coeff.imag for coeff in instruction.operator.coeffs])}"
)
targets = [
input_circuit.qubits.index(qargs[i])
for i in range(instruction.num_qubits)
]
terms = [term[0] for term in instruction.operator.to_list()]
coefficients = [coeff.real for coeff in instruction.operator.coeffs]
gate = {
"gate": instruction_name,
"targets": targets,
"terms": terms,
"coefficients": coefficients,
}
converted.update(gate)

# if there's a valid instruction after a measurement,
if num_meas > 0:
# see if any of the involved qubits have been measured,
Expand Down Expand Up @@ -473,7 +497,7 @@ def default(self, o):
for func in funcs:
try:
return func()
except Exception as exception:
except Exception as exception: # pylint: disable=broad-except
warnings.warn(
f"Unable to encode {o} using {func.__name__}: {exception}"
)
Expand Down
30 changes: 15 additions & 15 deletions qiskit_ionq/ionq_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"""Native gateset for IonQ hardware."""

from typing import Optional
import cmath
import math
import numpy
from qiskit.circuit.gate import Gate
Expand All @@ -47,8 +46,8 @@ class GPIGate(Gate):

GPI(\phi) =
\begin{pmatrix}
0 & e^{-i*2*\pi*\phi} \\
e^{i*2*\pi*\phi} & 0
0 & e^{-i*\phi} \\
e^{i*\phi} & 0
\end{pmatrix}
"""

Expand All @@ -58,9 +57,9 @@ def __init__(self, phi: ParameterValueType, label: Optional[str] = None):

def __array__(self, dtype=None):
"""Return a numpy.array for the GPI gate."""
top = cmath.exp(-self.params[0] * 2 * math.pi * 1j)
bot = cmath.exp(self.params[0] * 2 * math.pi * 1j)
return numpy.array([[0, top], [bot, 0]], dtype=dtype)
top = numpy.exp(-1j * self.params[0])
bottom = numpy.exp(1j * self.params[0])
return numpy.array([[0, top], [bottom, 0]], dtype=dtype)


class GPI2Gate(Gate):
Expand All @@ -75,9 +74,10 @@ class GPI2Gate(Gate):
.. math::

GPI2(\phi) =
\frac{1}{\sqrt{2}}
\begin{pmatrix}
1 & -i*e^{-i*2*\pi*\phi} \\
-i*e^{i*2*\pi*\phi} & 1
1 & -i*e^{-i*\phi} \\
-i*e^{i*\phi} & 1
\end{pmatrix}
"""

Expand All @@ -87,9 +87,9 @@ def __init__(self, phi: ParameterValueType, label: Optional[str] = None):

def __array__(self, dtype=None):
"""Return a numpy.array for the GPI2 gate."""
top = -1j * cmath.exp(self.params[0] * 2 * math.pi * -1j)
bot = -1j * cmath.exp(self.params[0] * 2 * math.pi * 1j)
return numpy.array([[1, top], [bot, 1]], dtype=dtype) / math.sqrt(2)
top = -1j * numpy.exp(-1j * self.params[0])
bottom = -1j * numpy.exp(1j * self.params[0])
return 1 / numpy.sqrt(2) * numpy.array([[1, top], [bottom, 1]], dtype=dtype)


class MSGate(Gate):
Expand Down Expand Up @@ -177,10 +177,10 @@ def __array__(self, dtype=None):
itheta2 = 1j * float(self.params[0]) * math.pi
return numpy.array(
[
[cmath.exp(-itheta2), 0, 0, 0],
[0, cmath.exp(itheta2), 0, 0],
[0, 0, cmath.exp(itheta2), 0],
[0, 0, 0, cmath.exp(-itheta2)],
[numpy.exp(-itheta2), 0, 0, 0],
[0, numpy.exp(itheta2), 0, 0],
[0, 0, numpy.exp(itheta2), 0],
[0, 0, 0, numpy.exp(-itheta2)],
],
dtype=dtype,
)
Loading
Loading