Skip to content

Commit 4f8e672

Browse files
Add missing CH gate (#624)
`CH` is defined in OpenQASM standard library, but was omitted in #592. --------- Co-authored-by: Mateo Uldemolins <m.uldemolins@gmail.com>
1 parent ff6349c commit 4f8e672

9 files changed

Lines changed: 251 additions & 146 deletions

File tree

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
graphix-qasm-parser @ git+https://github.com/TeamGraphix/graphix-qasm-parser@refs/pull/19/head
1+
# Keep in sync with noxfile.py
2+
graphix-qasm-parser @ git+https://github.com/TeamGraphix/graphix-qasm-parser@refs/pull/20/head

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
- `E` command in patterns.
2828
- The pretty-printing (`repr`) of instructions and commands is updated to use notation without parentheses: `repr(E((0, 1))) == "E(0, 1)"`.
2929

30+
- #694: CH gate is now supported (its support was missing as it is a standard OpenQASM gate).
31+
3032
### Changed
3133

3234
- #587:

‎graphix/instruction.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class InstructionKind(Enum):
6464
SX = enum.auto()
6565
SXDG = enum.auto()
6666
CY = enum.auto()
67+
CH = enum.auto()
6768
P = enum.auto()
6869
U = enum.auto()
6970
CJ = enum.auto()
@@ -317,6 +318,36 @@ class CY(_KindChecker, ControlledSingleTargetInstruction):
317318
kind: ClassVar[Literal[InstructionKind.CY]] = field(default=InstructionKind.CY, init=False)
318319

319320

321+
@dataclass(repr=False)
322+
class CH(_KindChecker, ControlledSingleTargetInstruction):
323+
r"""CH circuit instruction.
324+
325+
The CH gate applies the matrix
326+
327+
.. math::
328+
329+
\left[\begin{matrix}
330+
1 & 0 & 0 & 0\\
331+
0 & 1 & 0 & 0\\
332+
0 & 0 & \frac 1 {\sqrt 2} & \frac 1 {\sqrt 2}\\
333+
0 & 0 & \frac 1 {\sqrt 2} & -\frac 1 {\sqrt 2}
334+
\end{matrix}\right]
335+
336+
in the computational basis. The basis states use big-endian
337+
ordering, with the most significant qubit first. The qubits are
338+
numbered in the order ``control``, ``target``.
339+
340+
Attributes
341+
----------
342+
control : int
343+
Index of the control qubit.
344+
target : int
345+
Index of the target qubit.
346+
"""
347+
348+
kind: ClassVar[Literal[InstructionKind.CH]] = field(default=InstructionKind.CH, init=False)
349+
350+
320351
@dataclass(repr=False)
321352
class CNOT(_KindChecker, ControlledSingleTargetInstruction):
322353
r"""CNOT circuit instruction.
@@ -1153,6 +1184,7 @@ def visit(self, visitor: InstructionVisitor, *, copy: bool = False) -> GPHASE:
11531184
| CNOT
11541185
| CY
11551186
| CZ
1187+
| CH
11561188
| CCX
11571189
| RZZ
11581190
| SWAP
@@ -1219,6 +1251,7 @@ class Instruction:
12191251
CNOT: TypeAlias = CNOT
12201252
CY: TypeAlias = CY
12211253
CZ: TypeAlias = CZ
1254+
CH: TypeAlias = CH
12221255
CCX: TypeAlias = CCX
12231256
RZZ: TypeAlias = RZZ
12241257
SWAP: TypeAlias = SWAP
@@ -1236,6 +1269,7 @@ def __init__(self) -> None:
12361269
Instruction.CNOT
12371270
| Instruction.CY
12381271
| Instruction.CZ
1272+
| Instruction.CH
12391273
| Instruction.CJ
12401274
| Instruction.CCX
12411275
| Instruction.CRX

‎graphix/pattern.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,7 @@ def to_circuit(self) -> Circuit:
15151515
To extract a unitary circuit from a pattern, see :meth:`OpenGraph.to_circuit`.
15161516
"""
15171517
from graphix import Circuit # noqa: PLC0415 # Avoid circular imports
1518+
from graphix.transpiler import OutputKind # noqa: PLC0415 # Avoid circular imports
15181519

15191520
width = len(self.input_nodes)
15201521
all_nodes = [*self.input_nodes, *(cmd.node for cmd in self.__seq if cmd.kind == CommandKind.N)]
@@ -1589,7 +1590,7 @@ def to_circuit(self) -> Circuit:
15891590

15901591
active_qubit_idx = 0
15911592
for qubit in range(circuit.nqubit):
1592-
if qubit in circuit.active_qubits:
1593+
if circuit._visitor.output_kind[qubit] == OutputKind.Qubit:
15931594
idx = sorted_idx.index(qubit)
15941595
if active_qubit_idx != idx:
15951596
circuit.swap(qubit, sorted_idx[active_qubit_idx])

‎graphix/qasm3_exporter.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ def instruction_to_qasm3(instruction: InstructionType) -> Iterable[str]:
172172
yield qasm3_gate_call("cx", [qasm3_qubit(instruction.control), qasm3_qubit(instruction.target)])
173173
case InstructionKind.CY:
174174
yield qasm3_gate_call("cy", [qasm3_qubit(instruction.control), qasm3_qubit(instruction.target)])
175+
case InstructionKind.CH:
176+
yield qasm3_gate_call("ch", [qasm3_qubit(instruction.control), qasm3_qubit(instruction.target)])
175177
case InstructionKind.SWAP:
176178
yield qasm3_gate_call("swap", [qasm3_qubit(instruction.targets[i]) for i in (0, 1)])
177179
case InstructionKind.CSWAP:

0 commit comments

Comments
 (0)