Skip to main content
IBM Quantum Platform

OpenQASM 2

qiskit.qasm2

Qiskit es compatible con los programas OpenQASM 2.0, tanto para el análisis sintáctico en formatos Qiskit como para la exportación a OpenQASM 2.

Nota

OpenQASM 2 es un lenguaje simple, y no adecuado para la serialización general de objetos Qiskit. A continuación se analizan algunas alternativas, si eso es lo que busca.


API de análisis sintáctico

Este módulo contiene dos funciones públicas, ambas crean un QuantumCircuit a partir de un programa OpenQASM 2. load() toma un nombre de archivo, mientras que loads() toma el propio programa como cadena. Sus componentes internos son muy similares, por lo que ambos ofrecen casi la misma API.

load

qiskit.qasm2.load(filename, *, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)

GitHub

Parsear un programa OpenQASM 2 desde un archivo a un archivo QuantumCircuit. La ruta indicada debe estar codificada en ASCII o UTF-8 y contener el programa OpenQASM 2.

Nota

El analizador sintáctico interno de expresiones clásicas es recursivo y generará un RecursionError si alguna expresión requiere una profundidad excesiva para su evaluación. Esta profundidad máxima se puede ajustar mediante sys.setrecursionlimit(); el límite real es una décima parte de este valor.

Parámetros

  • filename (str |PathLike) – La ruta al archivo « OpenQASM 2».
  • include_path (Iterable[str |PathLike]) – orden de los directorios que se deben buscar al evaluar include las instrucciones.
  • include_input_directory (Literal['append', 'prepend'] | None) – Si se añade el directorio del archivo de entrada a include_path y, en caso afirmativo, si se añade a la búsqueda en último lugar o se antepone a la búsqueda en primer lugar. Pase None para suprimir la adición de este directorio por completo.
  • custom_instructions (Iterable[CustomInstruction]) – cualquier constructor personalizado que deba utilizarse para puertas específicas o instrucciones opacas durante el diseño del circuito. Consulte «Especificar instrucciones personalizadas» para obtener más información.
  • custom_classical (Iterable[CustomClassical]) – cualquier función clásica personalizada que deba utilizarse durante el análisis de expresiones clásicas. Para más información, consulta «Especificación de funciones clásicas personalizadas ».
  • strict (bool) – si se ejecuta en modo estricto.

Devuelve

Un objeto circuito que representa el mismo programa OpenQASM 2.

Tipo de retorno

QuantumCircuit

loads

qiskit.qasm2.loads(string, *, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)

GitHub

Parsear un programa OpenQASM 2 desde una cadena a un archivo QuantumCircuit.

Nota

El analizador sintáctico interno de expresiones clásicas es recursivo y generará un RecursionError si alguna expresión requiere una profundidad excesiva para su evaluación. Esta profundidad máxima se puede ajustar mediante sys.setrecursionlimit(); el límite real es una décima parte de este valor.

Parámetros

Devuelve

Un objeto circuito que representa el mismo programa OpenQASM 2.

Tipo de retorno

QuantumCircuit

Estas dos funciones de carga también reciben un argumento include_path, que es una iterable de nombres de directorio que se utiliza al buscar archivos en las sentencias include . Los directorios se prueban a partir del índice 0, y se utiliza la primera coincidencia. La importación qelib1.inc recibe un tratamiento especial; siempre se encuentra antes de buscar en la ruta include, y contiene exactamente el contenido del documento que describe el lenguaje OpenQASM 2. Las puertas en este archivo de inclusión se asignan a los objetos de puerta de la biblioteca de circuitos definidos por Qiskit.

Especificar instrucciones personalizadas

Puede ampliar los componentes cuánticos del lenguaje OpenQASM 2 pasando un iterable de información sobre instrucciones personalizadas como argumento custom_instructions. En los archivos que tienen definiciones compatibles para estas instrucciones, el constructor dado se utilizará en lugar de cualquier otra manipulación qiskit.qasm2 que se hubiera hecho. Estas instrucciones pueden marcarse opcionalmente como builtin, lo que hace que no requieran una declaración opaque o gate , pero ignorarán silenciosamente una declaración compatible. En cualquier caso, es un error proporcionar una instrucción personalizada que tenga un número diferente de parámetros o qubits como una instrucción definida en un programa analizado. Cada elemento del argumento iterable debe ser una clase de datos determinada:

CustomInstruction

class qiskit.qasm2.CustomInstruction(name, num_params, num_qubits, constructor, builtin=False)

GitHub

Bases: object

Información sobre una instrucción personalizada que debe definirse durante el análisis sintáctico.

Los campos name, num_params y num_qubits se explican por sí mismos. El campo constructor debe ser un objeto invocable con la firma *args -> Instruction, donde cada uno de los num_params args es un valor de punto flotante. La mayoría de las clases de puerta incorporadas en Qiskit tienen esta forma.

Hay un campo final builtin . Esta opción es opcional y, si se establece en true, hará que la instrucción se defina y esté disponible en el análisis sintáctico, incluso si no hay ninguna definición en ningún archivo OpenQASM 2 incluido.

Ejemplos

Indique al importador que utilice las funciones de Qiskit ECRGate y RZXGate para interpretar las declaraciones gate que se sabe que se han creado a partir de esos mismos objetos durante la exportación de OpenQASM 2:

from qiskit import qasm2
from qiskit.circuit import QuantumCircuit, library

qc = QuantumCircuit(2)
qc.ecr(0, 1)
qc.rzx(0.3, 0, 1)
qc.rzx(0.7, 1, 0)
qc.rzx(1.5, 0, 1)
qc.ecr(1, 0)

# This output string includes `gate ecr q0, q1 { ... }` and `gate rzx(p) q0, q1 { ... }`
# statements, since `ecr` and `rzx` are neither built-in gates nor in ``qelib1.inc``.
dumped = qasm2.dumps(qc)

# Tell the importer how to interpret the `gate` statements, which we know are safe
# because we controlled the input OpenQASM 2 source.
custom = [
    qasm2.CustomInstruction("ecr", 0, 2, library.ECRGate),
    qasm2.CustomInstruction("rzx", 1, 2, library.RZXGate),
]

loaded = qasm2.loads(dumped, custom_instructions=custom)

Parámetros

Esto puede ser especialmente útil cuando se trata de resolver ambigüedades en las convenciones de fase global de un programa OpenQASM 2. Para más detalles, consulte OpenQASM 2 Phase Conventions.

Especificar funciones clásicas personalizadas

De forma similar a las extensiones cuánticas anteriores, también puede ampliar el procesamiento realizado a las expresiones clásicas (argumentos a las puertas) pasando un iterable al argumento custom_classical a cualquiera de los cargadores. Esto necesita el name (un identificador válido OpenQASM 2), el número num_params de parámetros que toma, y un Python callable que implemente la función. La llamada a Python debe poder aceptar argumentos de coma flotante posicionales de num_params y debe devolver un flotante o un entero (que se convertirá a un flotante). Las funciones incorporadas no pueden anularse.

CustomClassical

class qiskit.qasm2.CustomClassical(name, num_params, callable, /)

Bases: object

Información sobre una función clásica personalizada que debe definirse en expresiones matemáticas.

El callable dado debe ser una función Python que toma num_params floats, y devuelve un float. El nombre es el identificador que hace referencia a él en el programa OpenQASM 2. Esto no puede chocar con ninguna puerta definida.

Modalidad estricta

Ambas funciones del cargador disponen de un modo "estricto" opcional. Por defecto, este analizador sintáctico es un poco más relajado que la especificación oficial: permite comas finales en las listas de parámetros; punto y coma innecesarios (declaración vacía); omitir la declaración de versión OPENQASM 2.0; ; y un par de otras mejoras de calidad de vida sin emitir ningún error. Puede utilizar el modo de letra de especificaciones con strict=True.


API de exportación

Al igual que otros módulos de serialización en Python, este módulo ofrece dos funciones públicas: dump() y dumps()que toman un QuantumCircuit y escriben un programa representativo de OpenQASM 2 en un objeto similar a un archivo o devuelven una cadena, respectivamente.

dump

qiskit.qasm2.dump(circuit, filename_or_stream, /)

GitHub

Volcar un circuito como programa OpenQASM 2 a un archivo o stream.

Parámetros

Eleva

QASM2ExportError - si el circuito no puede representarse mediante OpenQASM 2.

dumps

qiskit.qasm2.dumps(circuit, /)

GitHub

Exporte un circuito a un programa OpenQASM 2 en una cadena.

Parámetros

circuit (QuantumCircuit) – la dirección QuantumCircuit a exportar.

Devuelve

Una cadena OpenQASM 2 que representa el circuito.

Eleva

QASM2ExportError - si el circuito no puede representarse mediante OpenQASM 2.

Tipo de retorno

str


Errores

Este módulo define un tipo de error genérico que deriva de QiskitError que se puede utilizar como captura cuando te preocupas por fallos emitidos por la capa de interoperación específicamente.

QASM2Error

exception qiskit.qasm2.QASM2Error(*message)

GitHub

Bases: QiskitError

Un error general planteado por la capa de interoperabilidad OpenQASM 2.

Establece el mensaje de error.

En los casos en los que el lexer o el parser fallen debido a un archivo OpenQASM 2 no válido, las funciones de conversión lanzarán un error más específico con un mensaje que explique cuál es el fallo y en qué parte del archivo se ha producido.

QASM2ParseError

exception qiskit.qasm2.QASM2ParseError(*message)

GitHub

Bases: QASM2Error

Se ha producido un error al no poder analizar un archivo OpenQASM 2.

Establece el mensaje de error.

Cuando los exportadores fallan al exportar un circuito, probablemente porque tiene una estructura que no puede ser representada por OpenQASM 2.0, también emitirán un error personalizado.

QASM2ExportError

exception qiskit.qasm2.QASM2ExportError(*message)

GitHub

Bases: QASM2Error

Se ha producido un error al no poder convertir un objeto Qiskit en un formulario OpenQASM 2.

Establece el mensaje de error.


Ejemplos

ejemplos de exportación

Exportar un simple QuantumCircuit a una cadena OpenQASM 2:

import qiskit.qasm2
from qiskit.circuit import QuantumCircuit

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
print(qiskit.qasm2.dumps(qc))
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
measure q[0] -> c[0];
measure q[1] -> c[1];

Escribe lo mismo QuantumCircuit a un nombre de archivo dado:

qiskit.qasm2.dump(qc, "myfile.qasm")

Del mismo modo, se pueden utilizar os.PathLike como nombre de archivo:

import pathlib

qiskit.qasm2.dump(qc, pathlib.Path.home() / "myfile.qasm")

También se puede volcar el texto a un flujo ya abierto:

import io

with io.StringIO() as stream:
    qiskit.qasm2.dump(qc, stream)

Ejemplos de análisis sintáctico

Utilice loads() para importar un programa OpenQASM 2 en una cadena a un programa QuantumCircuit:

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()
     ┌───┐     ┌─┐
q_0: ┤ H ├──■──┤M├───
     └───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
          └───┘ ║ └╥┘
c: 2/═══════════╩══╩═
                0  1

Puede conseguir lo mismo si el programa está almacenado en un archivo utilizando en su lugar load() pasando el nombre del archivo como argumento:

import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")

OpenQASM 2 pueden incluir otros archivos OpenQASM 2 mediante la sentencia include . Puede influir en la ruta de búsqueda utilizada para encontrar estos archivos con el argumento include_path tanto para load() y loads(). Por defecto, sólo se busca en el directorio de trabajo actual.

import qiskit.qasm2
program = """
    include "other.qasm";
    // ... and so on
"""
circuit = qiskit.qasm2.loads(program, include_path=("/path/to/a", "/path/to/b", "."))

Sólo para load() existe un argumento extra include_input_directory, que puede utilizarse para 'append', 'prepend' o ignorar (None) el directorio del archivo cargado en la ruta de inclusión. Por defecto, este directorio se añade a la ruta de búsqueda, por lo que se intenta en último lugar, pero puede cambiarlo.

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
]

A veces es posible que desee influir en los Gate que el importador emite para determinadas instrucciones con nombre. Las puertas definidas por la sentencia include "qelib1.inc"; se asociarán automáticamente con una puerta de la biblioteca de circuitos Qiskit adecuada, pero puedes ampliarla:

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)

Del mismo modo, puede añadir nuevas funciones clásicas utilizadas durante la descripción de los argumentos a las puertas, tanto en el cuerpo principal del programa (que salen plegadas de forma constante) como dentro de los cuerpos de las puertas definidas (que se calculan bajo demanda). Aquí proporcionamos una versión Python de atan2(y, x), que matemáticamente es arctan(y/x)\arctan(y/x) pero manejando correctamente los cuadrantes angulares y los infinitos, y una función personalizada add_one :

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)

OpenQASM Convenciones de 2 fases

Como lenguaje, OpenQASM 2 no dispone de una forma de especificar la fase global de un programa completo, ni de definiciones de puertas concretas. Esto significa que los analizadores sintácticos del lenguaje pueden interpretar determinadas puertas con una fase global distinta de la que cabría esperar. Por ejemplo, la biblioteca estándar de facto de OpenQASM 2 qelib1.inc contiene definiciones de u1 y rz como las siguientes:

gate u1(lambda) q {
    U(0, 0, lambda) q;
}

gate rz(phi) a {
    u1(phi) a;
}

En otras palabras, rz parece ser un alias directo de u1. Sin embargo, la interpretación de u1 se especifica en la ecuación (3) del documento que describe el lenguaje como

u1(λ)=diag(1,eiλ)Rz(λ)u_1(\lambda) = \operatorname{diag}\bigl(1, e^{i\lambda}\bigr) \sim R_z(\lambda)

donde el símbolo \sim denota equivalencia sólo hasta una fase global. Al analizar OpenQASM 2, tenemos que elegir cómo manejar una distinción entre tales puertas; u1 se define en la prosa para ser diferente por una fase a rz, pero el lenguaje no está diseñado para representar esto.

La posición por defecto de Qiskit es interpretar un uso de la biblioteca estándar rz usando RZGatey un uso de u1 como el uso de la fase diferenciada U1Gate. Si deseas utilizar las convenciones de fase más implícitas por una interpretación directa de las declaraciones gate en el archivo de cabecera, puedes utilizar CustomInstruction para anular la forma en que Qiskit construye el circuito.

Para el estándar qelib1.inc incluir sólo hay un punto de diferencia, y por lo tanto la anulación necesaria para cambiar su convención de fase es:

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),
]

Esto utilizará la clase PhaseGate para representar la instrucción rz , que es igual (incluida la fase) a U1Gate:

Operator(qasm2.loads(program, custom_instructions=custom))
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,))

Compatibilidad con versiones anteriores

QuantumCircuit.from_qasm_str() y from_qasm_file() utilizado para hacer algunas adiciones sobre la especificación en bruto. Qiskit intentó originalmente utilizar OpenQASM 2 como una especie de formato de serialización, y amplió su comportamiento a medida que Qiskit se expandía. El nuevo analizador sintáctico, con todos sus valores por defecto, aplica la especificación de forma más estricta.

En particular, en los importadores heredados:

  • el include\path es efectivamente:

    1. <qiskit>/qasm/libsdonde <qiskit> es la raíz del paquete qiskit instalado;
    2. El directorio de trabajo actual.
  • hay instrucciones adicionales definidas en qelib1.inc:

    csx a, b

    Compuerta controlada X\sqrt X, correspondiente a CSXGate.

    cu(theta, phi, lambda, gamma) c, t

    La versión de cuatro parámetros de un control- UU, correspondiente a CUGate.

    rxx(theta) a, b

    Rotación de dos qubits alrededor del eje XXXX, correspondiente a RXXGate.

    rzz(theta) a, b

    Rotación de dos qubits alrededor del eje ZZZZ, correspondiente a RZZGate.

    rccx a, b, c

    La puerta XX de doble control, pero con diferencias de fase relativas respecto a la puerta Toffoli estándar. Esto debería corresponder a la puerta Qiskit RCCXGatepero el convertidor heredado no emitiría este tipo.

    rc3x a, b, c, d

    La puerta de triple control XX, pero con diferencias de fase relativas respecto a la definición estándar. Corresponde a RC3XGate.

    c3x a, b, c, d

    La puerta XX de triple control, correspondiente a C3XGate.

    c3sqrtx a, b, c, d

    La puerta X\sqrt X de triple control, correspondiente a C3SXGate.

    c4x a, b, c, d, e

    La puerta cuádruple controlada XX., correspondiente a C4XGate.

  • si se ha dado alguna definición opaque o gate para el nombre delay, intentan dar salida a una Delay en cada llamada. Para funcionar, esto espera una definición compatible con opaque delay(t) q;, donde el tiempo t se da en unidades de dt. El importador generará errores en la construcción si no hay exactamente un parámetro y un qubit, o si el parámetro no tiene valor entero.

  • están disponibles las funciones adicionales de la calculadora científica asin, acos y atan .

  • la gramática analizada es efectivamente la misma que el modo estricto de los nuevos importadores.

Puede emular este comportamiento en load() y loads() configurando include\path adecuadamente (intente inspeccionar la variable qiskit.__file__ para encontrar la ubicación instalada), y pasando una lista de CustomInstruction para cada una de las puertas personalizadas que te interesen. Para facilitar las cosas, ponemos a disposición tres tuplas, cada una de las cuales contiene un componente de una configuración equivalente al comportamiento del conversor heredado de Qiskit.

qiskit.qasm2.LEGACY_CUSTOM_INSTRUCTIONS

Una tupla que contiene las custom_instructions adicionales que los convertidores incorporados heredados de Qiskit utilizan si qelib1.inc está incluido, y hay alguna definición de una instrucción delay . Todas las puertas de la versión impresa de qelib1.inc y delay requieren una declaración de compatibilidad en el programa OpenQASM 2, pero las adiciones heredadas de Qiskit están marcadas como builtins, ya que no están presentes en ningún archivo de inclusión que vea este analizador.

qiskit.qasm2.LEGACY_CUSTOM_CLASSICAL

Una tupla que contiene las funciones custom_classical adicionales que los conversores incorporados heredados de Qiskit utilizan más allá de las especificadas por el documento. Se trata de las tres funciones trigonométricas inversas básicas: arcsin\arcsin, arccos\arccos y arctan\arctan.

qiskit.qasm2.LEGACY_INCLUDE_PATH

Una tupla que contiene el include_path exacto utilizado por el conversor Qiskit heredado.

En todas las compuertas definidas en la versión heredada de Qiskit de qelib1.inc y la instrucción delay , no importa cómo se definen y utilizan realmente las compuertas, el importador heredado siempre intentará dar salida a sus objetos personalizados para ellas. Esto puede dar lugar a errores durante la construcción del circuito, incluso después de un análisis correcto. No hay forma de emular este comportamiento erróneo con qiskit.qasm2ya que sólo una sentencia include "qelib1.inc"; o el argumento custom_instructions pueden hacer que se utilicen instrucciones Qiskit incorporadas, y las firmas de éstas coinciden entre sí.

Nota

Circuitos importados con load() y loads() con los ajustes de compatibilidad de legado anteriores deberían compararse igual a los creados por el importador de legado de Qiskit, siempre que no se definan puertas de usuario que no seanqelib1.inc . Las puertas definidas por el usuario se manejan de forma ligeramente diferente en el nuevo importador, y aunque deberían tener campos equivalentes definition este módulo utiliza una clase personalizada para cargar perezosamente la definición cuando se solicita (como la mayoría de los objetos Qiskit), en lugar de crearla ansiosamente durante el análisis sintáctico. Las reglas de comparación de Qiskit para puertas verán estos dos objetos como desiguales, aunque cualquier paso a través de transpile() para un backend particular debería producir los mismos circuitos de salida.


Alternativas

Los componentes del analizador sintáctico de este módulo comenzaron como un paquete separado de PyPI : qiskit-qasm2. Este paquete en la versión 0.5.3 se vendió en Qiskit Terra 0.24. Es posible que los cambios posteriores entre los dos paquetes no se mantengan necesariamente sincronizados.

Existe una versión más reciente de la especificación OpenQASM, la versión 3.0, que se describe en https://openqasm.com. Esto incluye muchas más facilidades para la programación clásica de alto nivel. Qiskit ya tiene un soporte rudimentario para OpenQASM 3; ver qiskit.qasm3 al respecto.

OpenQASM 2 no es un lenguaje de serialización adecuado para Qiskit's QuantumCircuit. Este módulo se proporciona con fines de interoperabilidad, no como un formato de serialización general. Si eso es lo que necesita, considere la posibilidad de utilizar qiskit.qpy en su lugar.

¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.