OpenQASM 2 e o Qiskit SDK
Versões dos pacotes
O código nesta página foi desenvolvido usando os seguintes requisitos. Recomendamos usar estas versões ou mais recentes.
qiskit[all]~=2.3.0
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
O Qiskit SDK fornece algumas ferramentas para converter entre representações OpenQASM de programas quânticos e a classe QuantumCircuit.
Importar um programa OpenQASM 2 para o Qiskit
Duas funções importam programas OpenQASM 2 para o Qiskit.
São elas: qasm2.load(), que recebe um nome de arquivo, e qasm2.loads(), que recebe o programa OpenQASM 2 como uma string.
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)
Consulte a API OpenQASM 2 do Qiskit para mais informações.
Importar programas simples
Para a maioria dos programas OpenQASM 2, você pode usar simplesmente qasm2.load e qasm2.loads com um único argumento.
Exemplo: importar um programa OpenQASM 2 como string
Use qasm2.loads() para importar um programa OpenQASM 2 como string em um 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
Exemplo: importar um programa OpenQASM 2 a partir de um arquivo
Use load() para importar um programa OpenQASM 2 de um arquivo em um QuantumCircuit:
import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")
Vincular gates OpenQASM 2 com gates do Qiskit
Por padrão, o importador OpenQASM 2 do Qiskit trata o arquivo de inclusão "qelib1.inc" como uma biblioteca padrão de facto.
O importador trata este arquivo como contendo exatamente os gates descritos no artigo original que define o OpenQASM 2.
O Qiskit usará os gates integrados da biblioteca de circuitos para representar os gates em "qelib1.inc".
Gates definidos no programa por instruções gate manuais do OpenQASM 2 serão, por padrão, construídos como subclasses de Gate do Qiskit personalizadas.
Você pode instruir o importador a usar classes Gate específicas para as instruções gate encontradas.
Você também pode usar este mecanismo para tratar nomes de gates adicionais como "integrados", ou seja, sem exigir uma definição explícita.
Se você especificar quais classes de gate usar para instruções gate fora de "qelib1.inc", o circuito resultante normalmente será mais eficiente para trabalhar.
A partir do Qiskit SDK v1.0, o exportador OpenQASM 2 do Qiskit (veja Exportar um circuito Qiskit para OpenQASM 2) ainda se comporta como se "qelib1.inc" tivesse mais gates do que realmente tem.
Isso significa que as configurações padrão do importador podem não conseguir importar um programa exportado pelo nosso exportador.
Veja o exemplo específico sobre como trabalhar com o exportador legado para resolver este problema.
Esta discrepância é um comportamento legado do Qiskit, e será resolvida em uma versão futura do Qiskit.
Para passar informações sobre uma instrução personalizada ao importador OpenQASM 2, use a classe qasm2.CustomInstruction.
Esta classe requer quatro informações, em ordem:
- O nome do gate, usado no programa OpenQASM 2
- O número de parâmetros de ângulo que o gate recebe
- O número de qubits sobre os quais o gate atua
- A classe ou função Python construtora do gate, que recebe os parâmetros do gate (mas não os qubits) como argumentos individuais
Se o importador encontrar uma definição gate que corresponda a uma instrução personalizada fornecida, usará essas informações personalizadas para reconstruir o objeto gate.
Se uma instrução gate for encontrada com o name de uma instrução personalizada, mas sem corresponder ao número de parâmetros e ao número de qubits, o importador lançará um QASM2ParseError, indicando a incompatibilidade entre as informações fornecidas e o programa.
Além disso, um quinto argumento builtin pode ser definido opcionalmente como True para tornar o gate automaticamente disponível no programa OpenQASM 2, mesmo que não seja definido explicitamente.
Se o importador encontrar uma definição explícita de gate para uma instrução personalizada integrada, ela será aceita silenciosamente.
Da mesma forma, se uma definição explícita do mesmo nome não for compatível com a instrução personalizada fornecida, um QASM2ParseError será lançado.
Isso é útil para compatibilidade com exportadores OpenQASM 2 mais antigos e com certas outras plataformas quânticas que tratam os "gates de base" de seu hardware como instruções integradas.
O Qiskit fornece um atributo de dados para trabalhar com programas OpenQASM 2 produzidos por versões legadas das capacidades de exportação OpenQASM 2 do Qiskit.
Este é o qasm2.LEGACY_CUSTOM_INSTRUCTIONS, que pode ser passado como argumento custom_instructions para qasm2.load() e qasm2.loads().
Exemplo: importar um programa criado pelo exportador legado do Qiskit
Este programa OpenQASM 2 usa gates que não estão na versão original de "qelib1.inc" sem declará-los, mas que são gates padrão na biblioteca do Qiskit.
Você pode usar qasm2.LEGACY_CUSTOM_INSTRUCTIONS para facilmente instruir o importador a usar o mesmo conjunto de gates que o exportador OpenQASM 2 do Qiskit usava 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,
)
Exemplo: usar uma classe de gate específica ao importar um programa OpenQASM 2
O Qiskit não consegue, em geral, verificar se a definição em uma instrução gate do OpenQASM 2 corresponde exatamente a um gate da biblioteca padrão do Qiskit.
Em vez disso, o Qiskit escolhe um gate personalizado usando a definição precisa fornecida.
Isso pode ser menos eficiente do que usar um dos gates padrão integrados ou um gate personalizado definido pelo usuário.
Você pode definir manualmente instruções gate com classes específicas.
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,
)
Exemplo: definir um novo gate integrado em um programa OpenQASM 2
Se o argumento builtin=True for definido, um gate personalizado não precisa ter uma definição associada.
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 funções clássicas personalizadas
O OpenQASM 2 inclui algumas funções clássicas integradas para usar em argumentos de gates.
Você pode estender a linguagem com mais funções usando o argumento custom_classical para qasm2.load() e qasm2.loads(), com a classe qasm2.CustomClassical.
Para definir uma função clássica personalizada, você deve fornecer:
- O nome da função conforme aparece no programa OpenQASM 2
- O número de argumentos de ponto flutuante que ela aceita
- Um objeto Python chamável que avalia a função
Todas as funções clássicas personalizadas definidas são tratadas como integradas à linguagem OpenQASM 2 pelo importador. Não existe uma maneira oficial dentro da linguagem OpenQASM 2 de definir novas funções; esta é uma extensão do Qiskit.
Exemplo: usar instruções clássicas personalizadas
Aqui fornecemos duas funções clássicas personalizadas.
A primeira é simples e apenas adiciona um ao seu input.
A segunda é a função math.atan2, que representa a operação matemática de forma ciente do quadrante.
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 estrito
Por padrão, este parser é mais relaxado do que a especificação oficial.
Ele permite vírgulas no final de listas de parâmetros; ponto-e-vírgulas desnecessários (instrução vazia); omissão da declaração de versão OPENQASM 2.0;; e diversas outras melhorias de qualidade de vida sem emitir erros.
No entanto, você pode usar o modo "letra da especificação" com strict=True.
Exportar um circuito Qiskit para OpenQASM 2
O Qiskit também pode exportar um QuantumCircuit para OpenQASM 2.
Você usa a função qasm2.dump() para gravar em um arquivo, e qasm2.dumps() para gravar em uma string.
Atualmente, essas funções têm uma interface muito simples: aceitam um circuito e, apenas no caso de qasm2.dump(), um local para gravar a saída.
O exportador OpenQASM 2 do Qiskit ainda assume uma versão legada e não padrão do arquivo de inclusão "qelib1.inc".
Isso será resolvido em uma versão futura do Qiskit, mas enquanto isso, se você precisar reimportar um programa OpenQASM 2 criado com o Qiskit, use o exemplo acima de como informar ao importador sobre os gates legados.
Exemplo: exportar um circuito para 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 passos
- Aprenda como gerar código OpenQASM no guia do IBM Quantum Composer.
- Consulte a referência da API OpenQASM 2 do Qiskit.
- Revise o tópico Verificar seu programa.
- Visite a Especificação ao Vivo do OpenQASM.