Skip to content

Commit

Permalink
Merge pull request #215 from BQSKit/controlled-qasm
Browse files Browse the repository at this point in the history
QASM support for singly-controlled ControlledGates.
  • Loading branch information
edyounis authored Jan 25, 2024
2 parents 1ee59f1 + 5463f9f commit 9463f52
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
27 changes: 27 additions & 0 deletions bqskit/ir/gates/composed/controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,33 @@ def __init__(
ctrl_U = np.kron(self.ctrl, U) + self.ihalf
self._utry = UnitaryMatrix(ctrl_U, self.radixes)

@property
def qasm_name(self) -> str:
"""
Override default `Gate.qasm_name` method.
If the core gate is a standard gate, this function will output
qasm in the form 'c+<gate_qasm>'. Otherwise an error will be raised.
Raises:
ValueError: If the core gate is non-standard in OpenQASM 2.0.
"""
_core_gate = self.gate.qasm_name
if self.num_controls <= 2:
_controls = 'c' * self.num_controls
else:
_controls = f'c{self.num_controls}'
qasm_name = _controls + _core_gate
supported_gates = ('cu1', 'cu2', 'cu3', 'cswap', 'c3x', 'c4x')
if qasm_name not in supported_gates:
raise ValueError(
f'Controlled gate {_core_gate} with {self.num_controls} '
'controls is not a standard OpenQASM 2.0 identifier. '
'To encode this gate, try decomposing it into gates with'
'standard identifiers.',
)
return qasm_name

def get_unitary(self, params: RealVector = []) -> UnitaryMatrix:
"""Return the unitary for this gate, see :class:`Unitary` for more."""
if hasattr(self, '_utry'):
Expand Down
102 changes: 102 additions & 0 deletions tests/ir/lang/test_controlled_qasm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from __future__ import annotations

from bqskit.ir.lang.qasm2 import OPENQASM2Language


class TestControlledQASM:
def test_cu1(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[2];\n'
'cu1(3.1415) q[0], q[1];\n'
)
circuit = OPENQASM2Language().decode(input_qasm)

output_qasm = circuit.to('qasm')

assert input_qasm == output_qasm

def test_cu2(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[2];\n'
'cu2(3.1415, 0.0) q[0], q[1];\n'
)
circuit = OPENQASM2Language().decode(input_qasm)

output_qasm = circuit.to('qasm')

assert input_qasm == output_qasm

def test_cu3(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[2];\n'
'cu3(3.1415, 0.0, -4.0) q[0], q[1];\n'
)
circuit = OPENQASM2Language().decode(input_qasm)

output_qasm = circuit.to('qasm')

assert input_qasm == output_qasm

def test_cswap(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[3];\n'
'cswap q[0], q[1], q[2];\n'
)
circuit = OPENQASM2Language().decode(input_qasm)

output_qasm = circuit.to('qasm')

assert input_qasm == output_qasm

def test_c3x(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[4];\n'
'c3x q[0], q[1], q[2], q[3];\n'
)
circuit = OPENQASM2Language().decode(input_qasm)

output_qasm = circuit.to('qasm')

assert input_qasm == output_qasm

def test_c4x(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[5];\n'
'c4x q[0], q[1], q[2], q[3], q[4];\n'
)
circuit = OPENQASM2Language().decode(input_qasm)

output_qasm = circuit.to('qasm')

assert input_qasm == output_qasm

def test_ch(self) -> None:

input_qasm = (
'OPENQASM 2.0;\n'
'include "qelib1.inc";\n'
'qreg q[2];\n'
'ch q[0], q[1];\n'
)
try:
OPENQASM2Language().decode(input_qasm)
except ValueError:
assert True

0 comments on commit 9463f52

Please sign in to comment.