qiskit-documentation/docs/api/qiskit/0.44/qasm2.mdx

436 lines
26 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: qasm2
description: API reference for qiskit.qasm2
in_page_toc_min_heading_level: 2
python_api_type: module
python_api_name: qiskit.qasm2
---
<span id="module-qiskit.qasm2" />
<span id="qiskit-qasm2" />
<span id="openqasm-2-qiskit-qasm2" />
# OpenQASM 2
<span id="module-qiskit.qasm2" />
`qiskit.qasm2`
Qiskit has support for interoperation with OpenQASM 2.0 programs, both parsing into Qiskit formats and exporting back to OpenQASM 2. The parsing components live in this module, while currently the export capabilities are limited to being the [`QuantumCircuit.qasm()`](qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm") method.
<Admonition title="Note" type="note">
OpenQASM 2 is a simple language, and not suitable for general serialisation of Qiskit objects. See [some discussion of alternatives below](#qasm2-alternatives), if that is what you are looking for.
</Admonition>
## Parsing API
This module contains two public functions, both of which create a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") from an OpenQASM 2 program. [`load()`](#qiskit.qasm2.load "qiskit.qasm2.load") takes a filename, while [`loads()`](#qiskit.qasm2.loads "qiskit.qasm2.loads") takes the program itself as a string. Their internals are very similar, so both offer almost the same API.
### load
<Function id="qiskit.qasm2.load" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/qasm2/__init__.py" signature="qiskit.qasm2.load(filename, *, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)">
Parse an OpenQASM 2 program from a file into a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"). The given path should be ASCII or UTF-8 encoded, and contain the OpenQASM 2 program.
**Parameters**
* **filename** ([*str*](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.12)") *|*[*PathLike*](https://docs.python.org/3/library/os.html#os.PathLike "(in Python v3.12)")) The OpenQASM 2 program in a string.
* **include\_path** ([*Iterable*](https://docs.python.org/3/library/typing.html#typing.Iterable "(in Python v3.12)")*\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.12)") *|*[*PathLike*](https://docs.python.org/3/library/os.html#os.PathLike "(in Python v3.12)")*]*) order of directories to search when evaluating `include` statements.
* **include\_input\_directory** ([*Literal*](https://docs.python.org/3/library/typing.html#typing.Literal "(in Python v3.12)")*\['append', 'prepend'] | None*) Whether to add the directory of the input file to the `include_path`, and if so, whether to *append* it to search last, or *prepend* it to search first. Pass `None` to suppress adding this directory entirely.
* **custom\_instructions** ([*Iterable*](https://docs.python.org/3/library/typing.html#typing.Iterable "(in Python v3.12)")*\[*[*CustomInstruction*](#qiskit.qasm2.CustomInstruction "qiskit.qasm2.parse.CustomInstruction")*]*) any custom constructors that should be used for specific gates or opaque instructions during circuit construction. See [Specifying custom instructions](#qasm2-custom-instructions) for more.
* **custom\_classical** ([*Iterable*](https://docs.python.org/3/library/typing.html#typing.Iterable "(in Python v3.12)")*\[*[*CustomClassical*](#qiskit.qasm2.CustomClassical "qiskit.qasm2.CustomClassical")*]*) any custom classical functions that should be used during the parsing of classical expressions. See [Specifying custom classical functions](#qasm2-custom-classical) for more.
* **strict** ([*bool*](https://docs.python.org/3/library/functions.html#bool "(in Python v3.12)")) whether to run in [strict mode](#qasm2-strict-mode).
**Returns**
A circuit object representing the same OpenQASM 2 program.
**Return type**
[*QuantumCircuit*](qiskit.circuit.QuantumCircuit "qiskit.circuit.quantumcircuit.QuantumCircuit")
</Function>
### loads
<Function id="qiskit.qasm2.loads" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/qasm2/__init__.py" signature="qiskit.qasm2.loads(string, *, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)">
Parse an OpenQASM 2 program from a string into a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit").
**Parameters**
* **string** ([*str*](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.12)")) The OpenQASM 2 program in a string.
* **include\_path** ([*Iterable*](https://docs.python.org/3/library/typing.html#typing.Iterable "(in Python v3.12)")*\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.12)") *|*[*PathLike*](https://docs.python.org/3/library/os.html#os.PathLike "(in Python v3.12)")*]*) order of directories to search when evaluating `include` statements.
* **custom\_instructions** ([*Iterable*](https://docs.python.org/3/library/typing.html#typing.Iterable "(in Python v3.12)")*\[*[*CustomInstruction*](#qiskit.qasm2.CustomInstruction "qiskit.qasm2.parse.CustomInstruction")*]*) any custom constructors that should be used for specific gates or opaque instructions during circuit construction. See [Specifying custom instructions](#qasm2-custom-instructions) for more.
* **custom\_classical** ([*Iterable*](https://docs.python.org/3/library/typing.html#typing.Iterable "(in Python v3.12)")*\[*[*CustomClassical*](#qiskit.qasm2.CustomClassical "qiskit.qasm2.CustomClassical")*]*) any custom classical functions that should be used during the parsing of classical expressions. See [Specifying custom classical functions](#qasm2-custom-classical) for more.
* **strict** ([*bool*](https://docs.python.org/3/library/functions.html#bool "(in Python v3.12)")) whether to run in [strict mode](#qasm2-strict-mode).
**Returns**
A circuit object representing the same OpenQASM 2 program.
**Return type**
[*QuantumCircuit*](qiskit.circuit.QuantumCircuit "qiskit.circuit.quantumcircuit.QuantumCircuit")
</Function>
Both of these loading functions also take an argument `include_path`, which is an iterable of directory names to use when searching for files in `include` statements. The directories are tried from index 0 onwards, and the first match is used. The import `qelib1.inc` is treated specially; it is always found before looking in the include path, and contains exactly the content of the [paper describing the OpenQASM 2 language](https://arxiv.org/abs/1707.03429). The gates in this include file are mapped to circuit-library gate objects defined by Qiskit.
<span id="qasm2-custom-instructions" />
### Specifying custom instructions
You can extend the quantum components of the OpenQASM 2 language by passing an iterable of information on custom instructions as the argument `custom_instructions`. In files that have compatible definitions for these instructions, the given `constructor` will be used in place of whatever other handling [`qiskit.qasm2`](#module-qiskit.qasm2 "qiskit.qasm2") would have done. These instructions may optionally be marked as `builtin`, which causes them to not require an `opaque` or `gate` declaration, but they will silently ignore a compatible declaration. Either way, it is an error to provide a custom instruction that has a different number of parameters or qubits as a defined instruction in a parsed program. Each element of the argument iterable should be a particular data class:
#### CustomInstruction
<Class id="qiskit.qasm2.CustomInstruction" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/qasm2/parse.py" signature="qiskit.qasm2.CustomInstruction(name, num_params, num_qubits, constructor, builtin=False)" modifiers="class">
Information about a custom instruction that should be defined during the parse.
The `name`, `num_params` and `num_qubits` fields are self-explanatory. The `constructor` field should be a callable object with signature `*args -> Instruction`, where each of the `num_params` `args` is a floating-point value. Most of the built-in Qiskit gate classes have this form.
There is a final `builtin` field. This is optional, and if set true will cause the instruction to be defined and available within the parsing, even if there is no definition in any included OpenQASM 2 file.
</Class>
This can be particularly useful when trying to resolve ambiguities in the global-phase conventions of an OpenQASM 2 program. See [OpenQASM 2 Phase Conventions](#qasm2-phase-conventions) for more details.
<span id="qasm2-custom-classical" />
### Specifying custom classical functions
Similar to the quantum extensions above, you can also extend the processing done to classical expressions (arguments to gates) by passing an iterable to the argument `custom_classical` to either loader. This needs the `name` (a valid OpenQASM 2 identifier), the number `num_params` of parameters it takes, and a Python callable that implements the function. The Python callable must be able to accept `num_params` positional floating-point arguments, and must return a float or integer (which will be converted to a float). Builtin functions cannot be overridden.
#### CustomClassical
<Class id="qiskit.qasm2.CustomClassical" signature="qiskit.qasm2.CustomClassical" modifiers="class">
Information about a custom classical function that should be defined in mathematical expressions.
The given callable must be a Python function that takes num\_params floats, and returns a float. The name is the identifier that refers to it in the OpenQASM 2 program. This cannot clash with any defined gates.
</Class>
<span id="qasm2-strict-mode" />
### Strict mode
Both of the loader functions have an optional “strict” mode. By default, this parser is a little bit more relaxed than the official specification: it allows trailing commas in parameter lists; unnecessary (empty-statement) semicolons; the `OPENQASM 2.0;` version statement to be omitted; and a couple of other quality-of-life improvements without emitting any errors. You can use the letter-of-the-spec mode with `strict=True`.
## Errors
This module defines a generic error type that derives from [`QiskitError`](exceptions#qiskit.exceptions.QiskitError "qiskit.exceptions.QiskitError") that can be used as a catch when you care about failures emitted by the interoperation layer specifically.
### QASM2Error
<Class id="qiskit.qasm2.QASM2Error" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/qasm2/exceptions.py" signature="qiskit.qasm2.QASM2Error(*message)" modifiers="exception">
A general error raised by the OpenQASM 2 interoperation layer.
Set the error message.
</Class>
In cases where the lexer or parser fails due to an invalid OpenQASM 2 file, the conversion functions will raise a more specific error with a message explaining what the failure is, and where in the file it occurred.
### QASM2ParseError
<Class id="qiskit.qasm2.QASM2ParseError" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/qasm2/exceptions.py" signature="qiskit.qasm2.QASM2ParseError(*message)" modifiers="exception">
An error raised because of a failure to parse an OpenQASM 2 file.
Set the error message.
</Class>
Similarly, a failure during the export of an OpenQASM 2 program will raise its own subclass of [`QASM2Error`](#qiskit.qasm2.QASM2Error "qiskit.qasm2.QASM2Error"):
### QASM2ExportError
<Class id="qiskit.qasm2.QASM2ExportError" github="https://github.com/qiskit/qiskit/tree/stable/0.25/qiskit/qasm2/exceptions.py" signature="qiskit.qasm2.QASM2ExportError(*message)" modifiers="exception">
An error raised because of a failure to convert a Qiskit object to an OpenQASM 2 form.
Set the error message.
</Class>
<span id="qasm2-examples" />
## Examples
Use [`loads()`](#qiskit.qasm2.loads "qiskit.qasm2.loads") to import an OpenQASM 2 program in a string into a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"):
```python
import qiskit.qasm2
program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
measure q -> c;
"""
circuit = qiskit.qasm2.loads(program)
circuit.draw()
```
```python
┌───┐ ┌─┐
q_0: ┤ H ├──■──┤M├───
└───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/═══════════╩══╩═
0 1
```
You can achieve the same thing if the program is stored in a file by using [`load()`](#qiskit.qasm2.load "qiskit.qasm2.load") instead, passing the filename as an argument:
```python
import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")
```
OpenQASM 2 files can include other OpenQASM 2 files via the `include` statement. You can influence the search path used for finding these files with the `include_path` argument to both [`load()`](#qiskit.qasm2.load "qiskit.qasm2.load") and [`loads()`](#qiskit.qasm2.loads "qiskit.qasm2.loads"). By default, only the current working directory is searched.
```python
import qiskit.qasm2
program = """
include "other.qasm";
// ... and so on
"""
circuit = qiskit.qasm2.loads(program, include_path=("/path/to/a", "/path/to/b", "."))
```
For [`load()`](#qiskit.qasm2.load "qiskit.qasm2.load") only, there is an extra argument `include_input_directory`, which can be used to either `'append'`, `'prepend'` or ignore (`None`) the directory of the loaded file in the include path. By default, this directory is appended to the search path, so it is tried last, but you can change this.
```python
import qiskit.qasm2
filenames = ["./subdirectory/a.qasm", "/path/to/b.qasm", "~/my.qasm"]
# Search the directory of each file before other parts of the include path.
circuits = [
qiskit.qasm2.load(filename, include_input_directory="prepend") for filename in filenames
]
# Override the include path, and don't search the directory of each file unless it's in the
# absolute path list.
circuits = [
qiskit.qasm2.load(
filename,
include_path=("/usr/include/qasm", "~/qasm/include"),
include_input_directory=None,
)
for filename in filenames
]
```
Sometimes you may want to influence the [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate") objects that the importer emits for given named instructions. Gates that are defined by the statement `include "qelib1.inc";` will automatically be associated with a suitable Qiskit circuit-library gate, but you can extend this:
```python
from qiskit.circuit import Gate
from qiskit.qasm2 import loads, CustomInstruction
class MyGate(Gate):
def __init__(self, theta):
super().__init__("my", 2, [theta])
class Builtin(Gate):
def __init__(self):
super().__init__("builtin", 1, [])
program = """
opaque my(theta) q1, q2;
qreg q[2];
my(0.5) q[0], q[1];
builtin q[0];
"""
customs = [
CustomInstruction(name="my", num_params=1, num_qubits=2, constructor=MyGate),
# Setting 'builtin=True' means the instruction doesn't require a declaration to be usable.
CustomInstruction("builtin", 0, 1, Builtin, builtin=True),
]
circuit = loads(program, custom_instructions=customs)
```
Similarly, you can add new classical functions used during the description of arguments to gates, both in the main body of the program (which come out constant-folded) and within the bodies of defined gates (which are computed on demand). Here we provide a Python version of `atan2(y, x)`, which mathematically is $\arctan(y/x)$ but correctly handling angle quadrants and infinities, and a custom `add_one` function:
```python
import math
from qiskit.qasm2 import loads, CustomClassical
program = """
include "qelib1.inc";
qreg q[2];
rx(atan2(pi, 3 + add_one(0.2))) q[0];
cx q[0], q[1];
"""
def add_one(x):
return x + 1
customs = [
# `atan2` takes two parameters, and `math.atan2` implements it.
CustomClassical("atan2", 2, math.atan2),
# Our `add_one` takes only one parameter.
CustomClassical("add_one", 1, add_one),
]
circuit = loads(program, custom_classical=customs)
```
<span id="qasm2-phase-conventions" />
## OpenQASM 2 Phase Conventions
As a language, OpenQASM 2 does not have a way to specify the global phase of a complete program, nor of particular gate definitions. This means that parsers of the language may interpret particular gates with a different global phase than what you might expect. For example, the *de facto* standard library of OpenQASM 2 `qelib1.inc` contains definitions of `u1` and `rz` as follows:
```python
gate u1(lambda) q {
U(0, 0, lambda) q;
}
gate rz(phi) a {
u1(phi) a;
}
```
In other words, `rz` appears to be a direct alias for `u1`. However, the interpretation of `u1` is specified in [equation (3) of the paper describing the language](https://arxiv.org/abs/1707.03429) as
$$
u_1(\lambda) = \operatorname{diag}\bigl(1, e^{i\lambda}\bigr) \sim R_z(\lambda)
$$
where the $\sim$ symbol denotes equivalence only up to a global phase. When parsing OpenQASM 2, we need to choose how to handle a distinction between such gates; `u1` is defined in the prose to be different by a phase to `rz`, but the language is not designed to represent this.
Qiskits default position is to interpret a usage of the standard-library `rz` using [`RZGate`](qiskit.circuit.library.RZGate "qiskit.circuit.library.RZGate"), and a usage of `u1` as using the phase-distinct [`U1Gate`](qiskit.circuit.library.U1Gate "qiskit.circuit.library.U1Gate"). If you wish to use the phase conventions more implied by a direct interpretation of the `gate` statements in the header file, you can use [`CustomInstruction`](#qiskit.qasm2.CustomInstruction "qiskit.qasm2.CustomInstruction") to override how Qiskit builds the circuit.
For the standard `qelib1.inc` include there is only one point of difference, and so the override needed to switch its phase convention is:
```python
from qiskit import qasm2
from qiskit.circuit.library import PhaseGate
from qiskit.quantum_info import Operator
program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
rz(pi / 2) q[0];
"""
custom = [
qasm2.CustomInstruction("rz", 1, 1, PhaseGate),
]
```
This will use Qiskits [`PhaseGate`](qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") class to represent the `rz` instruction, which is equal (including the phase) to [`U1Gate`](qiskit.circuit.library.U1Gate "qiskit.circuit.library.U1Gate"):
```python
Operator(qasm2.loads(program, custom_instructions=custom))
```
```python
Operator([[1.000000e+00+0.j, 0.000000e+00+0.j],
[0.000000e+00+0.j, 6.123234e-17+1.j]],
input_dims=(2,), output_dims=(2,))
```
<span id="qasm2-legacy-compatibility" />
## Legacy Compatibility
[`QuantumCircuit.from_qasm_str()`](qiskit.circuit.QuantumCircuit#from_qasm_str "qiskit.circuit.QuantumCircuit.from_qasm_str") and [`from_qasm_file()`](qiskit.circuit.QuantumCircuit#from_qasm_file "qiskit.circuit.QuantumCircuit.from_qasm_file") used to make a few additions on top of the raw specification. Qiskit originally tried to use OpenQASM 2 as a sort of serialisation format, and expanded its behaviour as Qiskit expanded. The new parser under all its defaults implements the specification more strictly.
The complete legacy code-paths are
```python
from qiskit.converters import ast_to_dag, dag_to_circuit
from qiskit.qasm import Qasm
def from_qasm_file(path: str):
dag_to_circuit(ast_to_dag(Qasm(filename=path).parse()))
def from_qasm_str(qasm_str: str):
dag_to_circuit(ast_to_dag(Qasm(data=qasm_str).parse()))
```
In particular, in the legacy importers:
* **the include\_path is effectively:**
1. `<qiskit>/qasm/libs`, where `<qiskit>` is the root of the installed `qiskit` package;
2. the current working directory.
* **there are additional instructions defined in `qelib1.inc`:**
**`csx a, b`**
Controlled $\sqrt X$ gate, corresponding to [`CSXGate`](qiskit.circuit.library.CSXGate "qiskit.circuit.library.CSXGate").
**`cu(theta, phi, lambda, gamma) c, t`**
The four-parameter version of a controlled-$U$, corresponding to [`CUGate`](qiskit.circuit.library.CUGate "qiskit.circuit.library.CUGate").
**`rxx(theta) a, b`**
Two-qubit rotation around the $XX$ axis, corresponding to [`RXXGate`](qiskit.circuit.library.RXXGate "qiskit.circuit.library.RXXGate").
**`rzz(theta) a, b`**
Two-qubit rotation around the $ZZ$ axis, corresponding to [`RZZGate`](qiskit.circuit.library.RZZGate "qiskit.circuit.library.RZZGate").
**`rccx a, b, c`**
The double-controlled $X$ gate, but with relative phase differences over the standard Toffoli gate. This *should* correspond to the Qiskit gate [`RCCXGate`](qiskit.circuit.library.RCCXGate "qiskit.circuit.library.RCCXGate"), but the legacy converter wouldnt actually output this type.
**`rc3x a, b, c, d`**
The triple-controlled $X$ gate, but with relative phase differences over the standard definition. Corresponds to [`RC3XGate`](qiskit.circuit.library.RC3XGate "qiskit.circuit.library.RC3XGate").
**`c3x a, b, c, d`**
The triple-controlled $X$ gate, corresponding to [`C3XGate`](qiskit.circuit.library.C3XGate "qiskit.circuit.library.C3XGate").
**`c3sqrtx a, b, c, d`**
The triple-controlled $\sqrt X$ gate, corresponding to [`C3SXGate`](qiskit.circuit.library.C3SXGate "qiskit.circuit.library.C3SXGate").
**`c4x a, b, c, d, e`**
The quadruple-controlled $X$ gate., corresponding to [`C4XGate`](qiskit.circuit.library.C4XGate "qiskit.circuit.library.C4XGate").
* if *any* `opaque` or `gate` definition was given for the name `delay`, they attempt to output a [`Delay`](qiskit.circuit.Delay "qiskit.circuit.Delay") instruction at each call. To function, this expects a definition compatible with `opaque delay(t) q;`, where the time `t` is given in units of `dt`. The importer will raise errors on construction if there was not exactly one parameter and one qubit, or if the parameter is not integer-valued.
* the additional scientific-calculator functions `asin`, `acos` and `atan` are available.
* the parsed grammar is effectively the same as [the strict mode of the new importers](#qasm2-strict-mode).
You can emulate this behaviour in [`load()`](#qiskit.qasm2.load "qiskit.qasm2.load") and [`loads()`](#qiskit.qasm2.loads "qiskit.qasm2.loads") by setting include\_path appropriately (try inspecting the variable `qiskit.__file__` to find the installed location), and by passing a list of [`CustomInstruction`](#qiskit.qasm2.CustomInstruction "qiskit.qasm2.CustomInstruction") instances for each of the custom gates you care about. To make things easier we make three tuples available, which each contain one component of a configuration that is equivalent to Qiskits legacy converter behaviour.
### qiskit.qasm2.LEGACY\_CUSTOM\_INSTRUCTIONS
<Attribute id="qiskit.qasm2.LEGACY_CUSTOM_INSTRUCTIONS">
A tuple containing the extra custom\_instructions that Qiskits legacy built-in converters used if `qelib1.inc` is included, and there is any definition of a `delay` instruction. The gates in the paper version of `qelib1.inc` and `delay` all require a compatible declaration statement to be present within the OpenQASM 2 program, but Qiskits legacy additions are all marked as builtins since they are not actually present in any include file this parser sees.
</Attribute>
### qiskit.qasm2.LEGACY\_CUSTOM\_CLASSICAL
<Attribute id="qiskit.qasm2.LEGACY_CUSTOM_CLASSICAL">
A tuple containing the extra custom\_classical functions that Qiskits legacy built-in converters use beyond those specified by the paper. This is the three basic inverse trigonometric functions: $\asin$, $\acos$ and $\atan$.
</Attribute>
### qiskit.qasm2.LEGACY\_INCLUDE\_PATH
<Attribute id="qiskit.qasm2.LEGACY_INCLUDE_PATH">
A tuple containing the exact include\_path used by the legacy Qiskit converter.
</Attribute>
On *all* the gates defined in Qiskits legacy version of `qelib1.inc` and the `delay` instruction, it does not matter how the gates are actually defined and used, the legacy importer will always attempt to output its custom objects for them. This can result in errors during the circuit construction, even after a successful parse. There is no way to emulate this buggy behaviour with [`qiskit.qasm2`](#module-qiskit.qasm2 "qiskit.qasm2"); only an `include "qelib1.inc";` statement or the custom\_instructions argument can cause built-in Qiskit instructions to be used, and the signatures of these match each other.
<Admonition title="Note" type="note">
Circuits imported with [`load()`](#qiskit.qasm2.load "qiskit.qasm2.load") and [`loads()`](#qiskit.qasm2.loads "qiskit.qasm2.loads") with the above legacy-compatibility settings should compare equal to those created by Qiskits legacy importer, provided no non-`qelib1.inc` user gates are defined. User-defined gates are handled slightly differently in the new importer, and while they should have equivalent [`definition`](qiskit.circuit.Instruction#definition "qiskit.circuit.Instruction.definition") fields on inspection, this module uses a custom class to lazily load the definition when it is requested (like most Qiskit objects), rather than eagerly creating it during the parse. Qiskits comparison rules for gates will see these two objects as unequal, although any pass through [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") for a particular backend should produce the same output circuits.
</Admonition>
<span id="qasm2-alternatives" />
## Alternatives
The parser components of this module started off as a separate PyPI package: [qiskit-qasm2](https://pypi.org/project/qiskit-qasm2/). This package at version 0.5.3 was vendored into Qiskit Terra 0.24. Any subsequent changes between the two packages may not necessarily be kept in sync.
There is a newer version of the OpenQASM specification, version 3.0, which is described at [https://openqasm.com](https://openqasm.com). This includes far more facilities for high-level classical programming. Qiskit has some rudimentary support for OpenQASM 3 already; see [`qiskit.qasm3`](qasm3#module-qiskit.qasm3 "qiskit.qasm3") for that.
OpenQASM 2 is not a suitable serialization language for Qiskits [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"). This module is provided for interoperability purposes, not as a general serialization format. If that is what you need, consider using [`qiskit.qpy`](qpy#module-qiskit.qpy "qiskit.qpy") instead.