Skip to content

Commit

Permalink
Deprecate and replace more qasm methods for Instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
jlapeyre committed Jul 6, 2023
1 parent 0c00b3d commit bd77bb8
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 9 deletions.
40 changes: 38 additions & 2 deletions qiskit/circuit/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from qiskit.qobj.qasm_qobj import QasmQobjInstruction
from qiskit.circuit.parameter import ParameterExpression
from qiskit.circuit.operation import Operation
from qiskit.utils.deprecation import deprecate_func
from .tools import pi_check

_CUTOFF_PRECISION = 1e-10
Expand Down Expand Up @@ -436,6 +437,39 @@ def __deepcopy__(self, _memo=None):
cpy._definition = copy.deepcopy(self._definition, _memo)
return cpy

def _qasmif(self, string):
"""Print an if statement if needed."""
if self.condition is None:
return string
if not isinstance(self.condition[0], ClassicalRegister):
raise QasmError(
"OpenQASM 2 can only condition on registers, but got '{self.condition[0]}'"
)
return "if(%s==%d) " % (self.condition[0].name, self.condition[1]) + string

@deprecate_func(
additional_msg=(
"Correct exporting to OpenQASM 2 is the responsibility of a larger exporter; it cannot "
"safely be done on an object-by-object basis without context. No replacement will be "
"provided, because the premise is wrong."
),
since="0.25.0",
)
def qasm(self):
"""Return a default OpenQASM string for the instruction.
Derived instructions may override this to print in a
different format (e.g. measure q[0] -> c[0];).
"""
name_param = self.name
if self.params:
name_param = "{}({})".format(
name_param,
",".join([pi_check(i, output="qasm", eps=1e-12) for i in self.params]),
)

return self._qasmif(name_param)

def broadcast_arguments(self, qargs, cargs):
"""
Validation of the arguments.
Expand Down Expand Up @@ -569,5 +603,7 @@ def _qasm(operation):
raise QasmError(
"OpenQASM 2 can only condition on registers, but got '{operation.condition[0]}'"
)
name_param = "if(%s==%d) " % (operation.condition[0].name, operation.condition[1]) + name_param
return name_param
name_param = (
"if(%s==%d) " % (operation.condition[0].name, operation.condition[1]) + name_param
)
return name_param
9 changes: 9 additions & 0 deletions qiskit/circuit/library/standard_gates/x.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from typing import Optional, Union, Type
from math import ceil, pi
import numpy
from qiskit.utils.deprecation import deprecate_func
from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.gate import Gate
import qiskit.circuit.instruction
Expand Down Expand Up @@ -569,6 +570,14 @@ def _define(self):

self.definition = qc

@deprecate_func(
additional_msg=(
"Correct exporting to OpenQASM 2 is the responsibility of a larger exporter; it cannot "
"safely be done on an object-by-object basis without context. No replacement will be "
"provided, because the premise is wrong."
),
since="0.25.0",
)
def qasm(self):
# Gross hack to override the Qiskit name with the name this gate has in Terra's version of
# 'qelib1.inc'. In general, the larger exporter mechanism should know about this to do the
Expand Down
18 changes: 12 additions & 6 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1738,16 +1738,22 @@ def qasm(
elif operation.name == "barrier":
qargs = ",".join(bit_labels[q] for q in instruction.qubits)
instruction_qasm = "barrier;" if not qargs else f"barrier {qargs};"
elif hasattr(operation, "has_qasm2") and not operation.has_qasm2():
raise CircuitError(
f"No QASM 2 representation is defined for operation {operation.name}"
)
else:
operation = _qasm2_define_custom_operation(
operation, existing_gate_names, gates_to_define
)

if not isinstance(operation, Instruction):
raise Exception(f"expecting Instruction got {type(operation)}")
# Insert qasm representation of the original instruction
if hasattr(operation, "qasm"):
name_param = operation.qasm()
else:
name_param = qiskit.circuit.instruction._qasm(operation)
if operation.name == "c3sx":
operation.name = "c3sqrtx"
name_param = qiskit.circuit.instruction._qasm(operation)
if operation.name == "c3sqrtx":
operation.name = "c3sx"
bits_qasm = ",".join(
bit_labels[j] for j in itertools.chain(instruction.qubits, instruction.clbits)
)
Expand Down Expand Up @@ -2822,7 +2828,7 @@ def _unroll_param_dict(
self, value_dict: Mapping[Parameter, ParameterValueType]
) -> dict[Parameter, ParameterValueType]:
unrolled_value_dict: dict[Parameter, ParameterValueType] = {}
for (param, value) in value_dict.items():
for param, value in value_dict.items():
if isinstance(param, ParameterVector):
if not len(param) == len(value):
raise CircuitError(
Expand Down
11 changes: 11 additions & 0 deletions qiskit/extensions/hamiltonian_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from qiskit.quantum_info.operators.predicates import is_hermitian_matrix
from qiskit.extensions.exceptions import ExtensionError
from qiskit.circuit.exceptions import CircuitError
from qiskit.utils.deprecation import deprecate_func

from .unitary import UnitaryGate

Expand Down Expand Up @@ -116,6 +117,16 @@ def _define(self):
qc._append(UnitaryGate(self.to_matrix()), q[:], [])
self.definition = qc

def has_qasm2(self):
"""Return `False` because no QASM2 representation is defined for HamiltonianGate."""
return False

@deprecate_func(
additional_msg=(
"This method raises an error stating that HamiltonianGate has no OpenQASM 2 definition."
),
since="0.25.0",
)
def qasm(self):
"""Raise an error, as QASM is not defined for the HamiltonianGate."""
raise ExtensionError("HamiltonianGate has no QASM definition.")
Expand Down
3 changes: 2 additions & 1 deletion test/python/circuit/test_hamiltonian_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import qiskit
from qiskit.extensions.hamiltonian_gate import HamiltonianGate, UnitaryGate
from qiskit.extensions.exceptions import ExtensionError
from qiskit.circuit.exceptions import CircuitError
from qiskit.test import QiskitTestCase
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.circuit import Parameter
Expand Down Expand Up @@ -97,7 +98,7 @@ def test_error_on_qasm(self):
matrix = np.zeros((2, 2))
qc.hamiltonian(operator=matrix, time=1, qubits=qr[0])

with self.assertRaises(ExtensionError):
with self.assertRaises(CircuitError):
qc.qasm()

def test_2q_hamiltonian(self):
Expand Down

0 comments on commit bd77bb8

Please sign in to comment.