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

Switch QuantumCircuit.from_qasm_str and from_qasm_file to new parser #9955

Merged
merged 2 commits into from
May 9, 2023
Merged
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
42 changes: 27 additions & 15 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
from qiskit.circuit.instruction import Instruction
from qiskit.circuit.gate import Gate
from qiskit.circuit.parameter import Parameter
from qiskit.qasm.qasm import Qasm
from qiskit.qasm.exceptions import QasmError
from qiskit.circuit.exceptions import CircuitError
from .parameterexpression import ParameterExpression, ParameterValueType
Expand Down Expand Up @@ -2504,11 +2503,23 @@ def from_qasm_file(path: str) -> "QuantumCircuit":

Args:
path (str): Path to the file for a QASM program

Return:
QuantumCircuit: The QuantumCircuit object for the input QASM

See also:
:func:`.qasm2.load`: the complete interface to the OpenQASM 2 importer.
"""
qasm = Qasm(filename=path)
return _circuit_from_qasm(qasm)
# pylint: disable=cyclic-import
from qiskit import qasm2

return qasm2.load(
path,
include_path=qasm2.LEGACY_INCLUDE_PATH,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
custom_classical=qasm2.LEGACY_CUSTOM_CLASSICAL,
strict=False,
)

@staticmethod
def from_qasm_str(qasm_str: str) -> "QuantumCircuit":
Expand All @@ -2518,9 +2529,20 @@ def from_qasm_str(qasm_str: str) -> "QuantumCircuit":
qasm_str (str): A QASM program string
Return:
QuantumCircuit: The QuantumCircuit object for the input QASM

See also:
:func:`.qasm2.loads`: the complete interface to the OpenQASM 2 importer.
"""
qasm = Qasm(data=qasm_str)
return _circuit_from_qasm(qasm)
# pylint: disable=cyclic-import
from qiskit import qasm2

return qasm2.loads(
qasm_str,
include_path=qasm2.LEGACY_INCLUDE_PATH,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
custom_classical=qasm2.LEGACY_CUSTOM_CLASSICAL,
strict=False,
)

@property
def global_phase(self) -> ParameterValueType:
Expand Down Expand Up @@ -4858,16 +4880,6 @@ def qubit_stop_time(self, *qubits: Union[Qubit, int]) -> float:
return 0 # If there are no instructions over bits


def _circuit_from_qasm(qasm: Qasm) -> "QuantumCircuit":
# pylint: disable=cyclic-import
from qiskit.converters import ast_to_dag
from qiskit.converters import dag_to_circuit

ast = qasm.parse()
dag = ast_to_dag(ast)
return dag_to_circuit(dag, copy_operations=False)


def _standard_compare(value1, value2):
if value1 < value2:
return -1
Expand Down
18 changes: 18 additions & 0 deletions releasenotes/notes/new-circuit-qasm2-methods-b1a06ee2859e2cce.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
upgrade:
- |
The OpenQASM 2 constructor methods on :class:`.QuantumCircuit`
(:meth:`~.QuantumCircuit.from_qasm_str` and :meth:`~.QuantumCircuit.from_qasm_file`) have been
switched to use the Rust-based parser added in Qiskit Terra 0.24. This should result in
significantly faster parsing times (10 times or more is not uncommon) and massively reduced
intermediate memory usage.

The :class:`.QuantumCircuit` methods are kept with the same interface for continuity; the
preferred way to access the OpenQASM 2 importer is to use :func:`.qasm2.load` and
:func:`.qasm2.loads`, which offer an expanded interface to control the parsing and construction.
fixes:
- |
The OpenQASM 2 circuit-constructor methods (:meth:`.QuantumCircuit.from_qasm_str` and
:meth:`~.QuantumCircuit.from_qasm_file`) will no longer error when encountering a ``gate``
definition that contains ``U`` or ``CX`` instructions. See `#5536
<https://github.com/Qiskit/qiskit-terra/issues/5536>`__.
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,6 @@ def test_fail_qasm_file(self):
"""
self.assertRaises(QiskitError, QuantumCircuit.from_qasm_file, "")

def test_fail_qasm_string(self):
"""
Test fail_qasm_string.

If all is correct we should get a QiskitError
"""
self.assertRaises(QiskitError, QuantumCircuit.from_qasm_str, "")

def test_qasm_text(self):
"""
Test qasm_text and get_circuit.
Expand Down Expand Up @@ -492,6 +484,21 @@ def test_from_qasm_str_delay(self):
expected.delay(172, qr[0])
self.assertEqualUnroll("u", circuit, expected)

def test_definition_with_u_cx(self):
"""Test that gate-definition bodies can use U and CX."""
qasm_string = """
OPENQASM 2.0;
gate bell q0, q1 { U(pi/2, 0, pi) q0; CX q0, q1; }
qreg q[2];
bell q[0], q[1];
"""
circuit = QuantumCircuit.from_qasm_str(qasm_string)
qr = QuantumRegister(2, "q")
expected = QuantumCircuit(qr)
expected.h(0)
expected.cx(0, 1)
self.assertEqualUnroll(["u", "cx"], circuit, expected)

def assertEqualUnroll(self, basis, circuit, expected):
"""Compares the dags after unrolling to basis"""
circuit_dag = circuit_to_dag(circuit)
Expand Down
Loading