Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Commit 4b6b843

Browse files
committed
Add missing gates to QISKIT_CUSTOM_INSTRUCTIONS
Turns out that Terra's legacy importer went pretty overboard with all the gates it added compared to the paper, and I missed several of them that are defined in the middle of the file, rather than added onto the end.
1 parent caed32c commit 4b6b843

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

docs/changelog.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
Changelog
33
=========
44

5+
Unreleased
6+
==========
7+
8+
* Added some missing gates to :data:`.QISKIT_CUSTOM_INSTRUCTIONS`; Qiskit's legacy importer
9+
made rather a lot of changes to the file as presented in the paper!
10+
511
0.3.1 (2023-01-20)
612
==================
713

docs/parse.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,44 @@ In particular, in the Qiskit importers:
5656
2. the current working directory.
5757

5858
* there are additional instructions defined in ``qelib1.inc``:
59+
``u0(gamma) a``
60+
This is ambiguous. Its provided definition suggests it is a no-op and that the `gamma`
61+
parameter is ignored, but a comment above it describes it as a delay for `gamma` times the
62+
length of the shortest single-qubit gate. In compatibility mode, we require `gamma` to be an
63+
integer, and set its definition to that many Qiskit :class:`.IGate`\ s.
64+
65+
``u(theta, phi, lambda) a``
66+
A synonym for the OpenQASM 2 builtin gate ``U``. Corresponds to
67+
:class:`~qiskit.circuit.library.UGate`.
68+
69+
``p(lambda) a``
70+
A synonym for the paper's ``u1``. Corresponds to :class:`~qiskit.circuit.library.PhaseGate`,
71+
which is a synonym of :class:`~qiskit.circuit.library.U1Gate`.
72+
73+
``sx a``
74+
:math:`\sqrt X` gate, corresponding to :class:`~qiskit.circuit.library.SXGate`.
75+
76+
``sxdg a``
77+
:math:`\sqrt X^\dagger` gate, corresponding to :class:`~qiskit.circuit.library.SXdgGate`.
78+
79+
``swap a, b``
80+
The swap gate, corresponding to :class:`~qiskit.circuit.library.SwapGate`.
81+
82+
``cswap a, b, c``
83+
The controlled swap gate, corresponding to :class:`~qiskit.circuit.library.CSwapGate`.
84+
85+
``crx(theta) a, b``
86+
Controlled rotation around the :math:`X` axis. Corresponds to
87+
:class:`~qiskit.circuit.library.CRXGate`.
88+
89+
``cry(theta) a, b``
90+
Controlled rotation around the :math:`Y` axis. Corresponds to
91+
:class:`~qiskit.circuit.library.CRYGate`.
92+
93+
``cp(lambda) a, b``
94+
Controlled phase gate, which is a synonym for the paper gate ``cu1``. Corresponds to
95+
:class:`~qiskit.circuit.library.CPhaseGate`.
96+
5997
``csx a, b``
6098
Controlled :math:`\sqrt X` gate, corresponding to :class:`~qiskit.circuit.library.CSXGate`.
6199

src-python/qiskit_qasm2/parse.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,28 @@ def _generate_delay(t: float):
8989
return Delay(int(t), unit="dt")
9090

9191

92+
class _U0Gate(Gate):
93+
def __init__(self, count):
94+
if int(count) != count:
95+
raise QASM2ParseError("the number of single-qubit delay lengths must be an integer")
96+
super().__init__("u0", 1, [count])
97+
98+
def _define(self):
99+
self._definition = QuantumCircuit(1)
100+
for _ in [None] * self.params[0]:
101+
self._definition.id(0)
102+
103+
92104
QISKIT_CUSTOM_INSTRUCTIONS = (
93105
CustomInstruction("u3", 3, 1, lib.U3Gate),
94106
CustomInstruction("u2", 2, 1, lib.U2Gate),
95107
CustomInstruction("u1", 1, 1, lib.U1Gate),
96108
CustomInstruction("cx", 0, 2, lib.CXGate),
97109
# The Qiskit parser emits IGate for 'id', even if that is not strictly accurate in Terra < 0.24.
98110
CustomInstruction("id", 0, 1, lib.IGate),
111+
CustomInstruction("u0", 1, 1, _U0Gate, builtin=True),
112+
CustomInstruction("u", 3, 1, lib.UGate, builtin=True),
113+
CustomInstruction("p", 1, 1, lib.PhaseGate, builtin=True),
99114
CustomInstruction("x", 0, 1, lib.XGate),
100115
CustomInstruction("y", 0, 1, lib.YGate),
101116
CustomInstruction("z", 0, 1, lib.ZGate),
@@ -107,12 +122,19 @@ def _generate_delay(t: float):
107122
CustomInstruction("rx", 1, 1, lib.RXGate),
108123
CustomInstruction("ry", 1, 1, lib.RYGate),
109124
CustomInstruction("rz", 1, 1, lib.RZGate),
125+
CustomInstruction("sx", 0, 1, lib.SXGate, builtin=True),
126+
CustomInstruction("sxdg", 0, 1, lib.SXdgGate, builtin=True),
110127
CustomInstruction("cz", 0, 2, lib.CZGate),
111128
CustomInstruction("cy", 0, 2, lib.CYGate),
129+
CustomInstruction("swap", 0, 2, lib.SwapGate, builtin=True),
112130
CustomInstruction("ch", 0, 2, lib.CHGate),
113131
CustomInstruction("ccx", 0, 3, lib.CCXGate),
132+
CustomInstruction("cswap", 0, 3, lib.CSwapGate, builtin=True),
133+
CustomInstruction("crx", 1, 2, lib.CRXGate, builtin=True),
134+
CustomInstruction("cry", 1, 2, lib.CRYGate, builtin=True),
114135
CustomInstruction("crz", 1, 2, lib.CRZGate),
115136
CustomInstruction("cu1", 1, 2, lib.CU1Gate),
137+
CustomInstruction("cp", 1, 2, lib.CPhaseGate, builtin=True),
116138
CustomInstruction("cu3", 3, 2, lib.CU3Gate),
117139
CustomInstruction("csx", 0, 2, lib.CSXGate, builtin=True),
118140
CustomInstruction("cu", 4, 2, lib.CUGate, builtin=True),

tests/test_structure.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,15 @@ def test_qelib1_include_overridden(self):
11981198
def test_qiskit_extra_builtins(self):
11991199
program = """
12001200
qreg q[5];
1201+
u(0.5 ,0.25, 0.125) q[0];
1202+
p(0.5) q[0];
1203+
sx q[0];
1204+
sxdg q[0];
1205+
swap q[0], q[1];
1206+
cswap q[0], q[1], q[2];
1207+
crx(0.5) q[0], q[1];
1208+
cry(0.5) q[0], q[1];
1209+
cp(0.5) q[0], q[1];
12011210
csx q[0], q[1];
12021211
cu(0.5, 0.25, 0.125, 0.0625) q[0], q[1];
12031212
rxx(0.5) q[0], q[1];
@@ -1212,6 +1221,15 @@ def test_qiskit_extra_builtins(self):
12121221
program, custom_instructions=qiskit_qasm2.QISKIT_CUSTOM_INSTRUCTIONS
12131222
)
12141223
qc = QuantumCircuit(QuantumRegister(5, "q"))
1224+
qc.append(lib.UGate(0.5, 0.25, 0.125), [0])
1225+
qc.append(lib.PhaseGate(0.5), [0])
1226+
qc.append(lib.SXGate(), [0])
1227+
qc.append(lib.SXdgGate(), [0])
1228+
qc.append(lib.SwapGate(), [0, 1])
1229+
qc.append(lib.CSwapGate(), [0, 1, 2])
1230+
qc.append(lib.CRXGate(0.5), [0, 1])
1231+
qc.append(lib.CRYGate(0.5), [0, 1])
1232+
qc.append(lib.CPhaseGate(0.5), [0, 1])
12151233
qc.append(lib.CSXGate(), [0, 1])
12161234
qc.append(lib.CUGate(0.5, 0.25, 0.125, 0.0625), [0, 1])
12171235
qc.append(lib.RXXGate(0.5), [0, 1])
@@ -1223,6 +1241,14 @@ def test_qiskit_extra_builtins(self):
12231241
qc.append(lib.C4XGate(), [0, 1, 2, 3, 4])
12241242
assert parsed == qc
12251243

1244+
# There's also the 'u0' gate, but this is weird so we don't wildly care what its definition
1245+
# is and it has no Qiskit equivalent, so we'll just test that it using it doesn't produce an
1246+
# error.
1247+
parsed = qiskit_qasm2.loads(
1248+
'qreg q[1]; u0(1) q[0];', custom_instructions=qiskit_qasm2.QISKIT_CUSTOM_INSTRUCTIONS
1249+
)
1250+
assert parsed.data[0].operation.name == "u0"
1251+
12261252
def test_qiskit_override_delay_opaque(self):
12271253
program = """
12281254
opaque delay(t) q;

0 commit comments

Comments
 (0)