Saltar al contenido principal

OpenQASM 2 y el SDK de Qiskit

Versiones de paquetes

El código de esta página fue desarrollado con los siguientes requisitos. Recomendamos usar estas versiones o más recientes.

qiskit[all]~=2.3.0
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit

El SDK de Qiskit proporciona algunas herramientas para convertir entre representaciones OpenQASM de programas cuánticos y la clase QuantumCircuit.

Importar un programa OpenQASM 2 en Qiskit

Hay dos funciones para importar programas OpenQASM 2 en Qiskit. Estas son qasm2.load(), que recibe un nombre de archivo, y qasm2.loads(), que recibe el programa OpenQASM 2 como cadena de texto.

import qiskit.qasm2

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

Consulta la API de OpenQASM 2 de Qiskit para obtener más información.

Importar programas simples

Para la mayoría de los programas OpenQASM 2, puedes usar qasm2.load y qasm2.loads con un solo argumento.

Ejemplo: importar un programa OpenQASM 2 como cadena de texto

Usa qasm2.loads() para importar un programa OpenQASM 2 como cadena de texto en un 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

Ejemplo: importar un programa OpenQASM 2 desde un archivo

Usa load() para importar un programa OpenQASM 2 desde un archivo en un QuantumCircuit:

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

Vincular gates de OpenQASM 2 con gates de Qiskit

Por defecto, el importador de OpenQASM 2 de Qiskit trata el archivo de inclusión "qelib1.inc" como una biblioteca estándar de facto. El importador trata este archivo como si contuviera exactamente los gates descritos en el artículo original que define OpenQASM 2. Qiskit usará los gates integrados de la biblioteca de circuitos para representar los gates en "qelib1.inc". Los gates definidos en el programa mediante sentencias gate de OpenQASM 2 se construirán, por defecto, como subclases personalizadas de Gate de Qiskit.

Puedes indicarle al importador que use clases Gate específicas para las sentencias gate que encuentre. También puedes usar este mecanismo para tratar nombres de gates adicionales como "integrados", es decir, que no requieran una definición explícita. Si especificas qué clases de Gate usar para sentencias gate fuera de "qelib1.inc", el circuito resultante será generalmente más eficiente de trabajar.

aviso

A partir de la versión v1.0 del SDK de Qiskit, el exportador de OpenQASM 2 de Qiskit (consulta Exportar un circuito de Qiskit a OpenQASM 2) todavía se comporta como si "qelib1.inc" tuviera más gates de los que realmente tiene. Esto significa que la configuración predeterminada del importador podría no ser capaz de importar un programa exportado por nuestro exportador. Consulta el ejemplo específico sobre cómo trabajar con el exportador heredado para resolver este problema.

Esta discrepancia es un comportamiento heredado de Qiskit y se resolverá en una versión posterior de Qiskit.

Para pasar información sobre una instrucción personalizada al importador de OpenQASM 2, usa la clase qasm2.CustomInstruction. Esta requiere cuatro datos en orden:

  • El nombre del gate, tal como aparece en el programa OpenQASM 2
  • El número de parámetros angulares que acepta el gate
  • El número de qubits sobre los que actúa el gate
  • La clase o función constructora de Python para el gate, que recibe los parámetros del gate (pero no los qubits) como argumentos individuales

Si el importador encuentra una definición gate que coincide con una instrucción personalizada dada, usará esa información personalizada para reconstruir el objeto gate. Si se encuentra una sentencia gate que coincide con el name de una instrucción personalizada, pero no coincide con el número de parámetros ni con el número de qubits, el importador lanzará un QASM2ParseError para indicar la discrepancia entre la información proporcionada y el programa.

Además, un quinto argumento builtin puede establecerse opcionalmente en True para hacer que el gate esté disponible automáticamente dentro del programa OpenQASM 2, incluso si no está definido explícitamente. Si el importador encuentra una definición gate explícita para una instrucción personalizada integrada, la aceptará silenciosamente. Como antes, si una definición explícita del mismo nombre no es compatible con la instrucción personalizada proporcionada, se lanzará un QASM2ParseError. Esto es útil para la compatibilidad con exportadores de OpenQASM 2 más antiguos y con ciertas plataformas cuánticas que tratan los "gates base" de su hardware como instrucciones integradas.

Qiskit proporciona un atributo de datos para trabajar con programas OpenQASM 2 producidos por versiones antiguas de las capacidades de exportación de OpenQASM 2 de Qiskit. Este es qasm2.LEGACY_CUSTOM_INSTRUCTIONS, que puede pasarse como argumento custom_instructions a qasm2.load() y qasm2.loads().

Ejemplo: importar un programa creado por el exportador heredado de Qiskit

Este programa OpenQASM 2 utiliza gates que no están en la versión original de "qelib1.inc" sin declararlos, pero son gates estándar en la biblioteca de Qiskit. Puedes usar qasm2.LEGACY_CUSTOM_INSTRUCTIONS para indicarle fácilmente al importador que use el mismo conjunto de gates que el exportador de OpenQASM 2 de Qiskit usaba anteriormente.

from qiskit import qasm2

program = """
OPENQASM 2.0;
include "qelib1.inc";

qreg q[4];
creg c[4];

h q[0];
cx q[0], q[1];

// 'rxx' is not actually in `qelib1.inc`,
// but Qiskit used to behave as if it were.
rxx(0.75) q[2], q[3];

measure q -> c;
"""
circuit = qasm2.loads(
program,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
)

Ejemplo: usar una clase de gate particular al importar un programa OpenQASM 2

En general, Qiskit no puede verificar si la definición en una sentencia gate de OpenQASM 2 corresponde exactamente a un gate de la biblioteca estándar de Qiskit. En cambio, Qiskit elige un gate personalizado usando la definición exacta proporcionada. Esto puede ser menos eficiente que usar uno de los gates estándar integrados o un gate personalizado definido por el usuario. Puedes definir manualmente sentencias gate con clases particulares.

from qiskit import qasm2
from qiskit.circuit import Gate
from qiskit.circuit.library import RZXGate

# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])

custom_instructions = [
# Link the OpenQASM 2 name 'my' with our custom gate.
qasm2.CustomInstruction("my", 2, 1, MyGate),
# Link the OpenQASM 2 name 'rzx' with Qiskit's
# built-in RZXGate.
qasm2.CustomInstruction("rzx", 1, 2, RZXGate),
]

program = """
OPENQASM 2.0;

gate my(theta, phi) q {
U(theta / 2, phi, -theta / 2) q;
}
gate rzx(theta) a, b {
// It doesn't matter what definition is
// supplied, if the parameters match;
// Qiskit will still use `RZXGate`.
}

qreg q[2];
my(0.25, 0.125) q[0];
rzx(pi) q[0], q[1];
"""

circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)

Ejemplo: definir un nuevo gate integrado en un programa OpenQASM 2

Si se establece el argumento builtin=True, un gate personalizado no necesita tener una definición asociada.

from qiskit import qasm2
from qiskit.circuit import Gate

# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])

custom_instructions = [
qasm2.CustomInstruction("my", 2, 1, MyGate, builtin=True),
]

program = """
OPENQASM 2.0;
qreg q[1];

my(0.25, 0.125) q[0];
"""

circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)

Definir funciones clásicas personalizadas

OpenQASM 2 incluye algunas funciones clásicas integradas para usar en los argumentos de los gates. Puedes extender el lenguaje con más funciones usando el argumento custom_classical de qasm2.load() y qasm2.loads(), junto con la clase qasm2.CustomClassical.

Para definir una función clásica personalizada, debes proporcionar:

  • El nombre de la función tal como aparece en el programa OpenQASM 2
  • El número de argumentos de punto flotante que acepta
  • Un objeto Python invocable que evalúe la función

Todas las funciones clásicas personalizadas definidas se tratan como integradas al lenguaje OpenQASM 2 por el importador. No existe una forma oficial dentro del lenguaje OpenQASM 2 para definir nuevas funciones; esta es una extensión de Qiskit.

Ejemplo: usar instrucciones clásicas personalizadas

Aquí proporcionamos dos funciones clásicas personalizadas. La primera es simple y simplemente suma uno a su entrada. La segunda es la función math.atan2, que representa la operación matemática arctan(y/x)\arctan(y/x) de forma consciente del cuadrante.

import math
from qiskit import qasm2

program = """
include "qelib1.inc";
qreg q[2];
rx(arctan(pi, 3 + add_one(0.2))) q[0];
cx q[0], q[1];
"""

def add_one(x):
return x + 1

customs = [
# Our `add_one` takes only one parameter.
qasm2.CustomClassical("add_one", 1, add_one),
# `arctan` takes two parameters, and `math.atan2` implements it.
qasm2.CustomClassical("arctan", 2, math.atan2),
]
circuit = qasm2.loads(program, custom_classical=customs)

Modo estricto

Por defecto, este analizador es más permisivo que la especificación oficial. Permite comas finales en las listas de parámetros; puntos y coma innecesarios (sentencias vacías); omisión de la sentencia de versión OPENQASM 2.0;; y otras mejoras de calidad de uso sin emitir errores. Sin embargo, puedes usar el modo "letra de la especificación" con strict=True.

Exportar un circuito de Qiskit a OpenQASM 2

Qiskit también puede exportar un QuantumCircuit a OpenQASM 2. Usa la función qasm2.dump() para escribir en un archivo, y qasm2.dumps() para escribir en una cadena de texto. Actualmente estas funciones tienen una interfaz muy simple: aceptan un circuito y, solo en el caso de qasm2.dump(), una ubicación donde escribir la salida.

aviso

El exportador de OpenQASM 2 de Qiskit todavía asume una versión heredada y no estándar del archivo de inclusión "qelib1.inc". Esto se resolverá en una versión posterior de Qiskit, pero mientras tanto, si necesitas volver a importar un programa OpenQASM 2 creado con Qiskit, usa el ejemplo anterior sobre cómo indicarle al importador los gates heredados.

Ejemplo: exportar un circuito a OpenQASM 2

from qiskit import QuantumCircuit, qasm2

# Define any circuit.
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])

# Export to a string.
program = qasm2.dumps(circuit)

# Export to a file.
qasm2.dump(circuit, "my_file.qasm")

Próximos pasos

Recomendaciones