Aller au contenu principal

OpenQASM 2 et le SDK Qiskit

Versions des packages

Le code de cette page a été développé avec les dépendances suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

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

Le SDK Qiskit fournit des outils pour convertir entre les représentations OpenQASM de programmes quantiques et la classe QuantumCircuit.

Importer un programme OpenQASM 2 dans Qiskit

Deux fonctions permettent d'importer des programmes OpenQASM 2 dans Qiskit. Il s'agit de qasm2.load(), qui prend un nom de fichier, et de qasm2.loads(), qui prend le programme OpenQASM 2 sous forme de chaîne de caractères.

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 la référence de l'API OpenQASM 2 de Qiskit pour plus d'informations.

Importer des programmes simples

Pour la plupart des programmes OpenQASM 2, tu peux simplement utiliser qasm2.load et qasm2.loads avec un seul argument.

Exemple : importer un programme OpenQASM 2 sous forme de chaîne

Utilise qasm2.loads() pour importer un programme OpenQASM 2 sous forme de chaîne dans 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

Exemple : importer un programme OpenQASM 2 depuis un fichier

Utilise load() pour importer un programme OpenQASM 2 depuis un fichier dans un QuantumCircuit :

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

Par défaut, l'importateur OpenQASM 2 de Qiskit traite le fichier d'inclusion "qelib1.inc" comme une bibliothèque standard de facto. L'importateur considère ce fichier comme contenant précisément les portes décrites dans l'article original définissant OpenQASM 2. Qiskit utilisera les portes intégrées de la bibliothèque de circuits pour représenter les portes de "qelib1.inc". Les portes définies dans le programme via des instructions gate OpenQASM 2 manuelles seront, par défaut, construites comme des sous-classes personnalisées de Qiskit Gate.

Tu peux indiquer à l'importateur d'utiliser des classes Gate spécifiques pour les instructions gate rencontrées. Tu peux aussi utiliser ce mécanisme pour traiter des noms de portes supplémentaires comme « intégrés », c'est-à-dire ne nécessitant pas de définition explicite. Si tu spécifies quelles classes de portes utiliser pour les instructions gate hors de "qelib1.inc", le circuit résultant sera généralement plus efficace à manipuler.

avertissement

Depuis le SDK Qiskit v1.0, l'exportateur OpenQASM 2 de Qiskit (voir Exporter un circuit Qiskit vers OpenQASM 2) se comporte toujours comme si "qelib1.inc" contenait plus de portes qu'il n'en contient réellement. Cela signifie que les paramètres par défaut de l'importateur pourraient ne pas être capables d'importer un programme exporté par notre exportateur. Consulte l'exemple spécifique sur l'utilisation de l'exportateur hérité pour résoudre ce problème.

Cette divergence est un comportement hérité de Qiskit, et elle sera corrigée dans une prochaine version de Qiskit.

Pour transmettre des informations sur une instruction personnalisée à l'importateur OpenQASM 2, utilise la classe qasm2.CustomInstruction. Celle-ci requiert quatre informations, dans l'ordre :

  • Le nom de la porte, tel qu'il apparaît dans le programme OpenQASM 2
  • Le nombre de paramètres angulaires que la porte accepte
  • Le nombre de qubits sur lesquels la porte agit
  • La classe ou fonction constructeur Python de la porte, qui prend les paramètres de la porte (mais pas les qubits) comme arguments individuels

Si l'importateur rencontre une définition gate correspondant à une instruction personnalisée donnée, il utilisera ces informations pour reconstruire l'objet porte. Si une instruction gate correspond au name d'une instruction personnalisée mais ne correspond pas au nombre de paramètres ou au nombre de qubits, l'importateur lèvera une erreur QASM2ParseError, indiquant une incompatibilité entre les informations fournies et le programme.

De plus, un cinquième argument builtin peut optionnellement être défini à True pour rendre la porte automatiquement disponible dans le programme OpenQASM 2, même si elle n'est pas explicitement définie. Si l'importateur rencontre une définition gate explicite pour une instruction personnalisée intégrée, il l'acceptera silencieusement. Comme précédemment, si une définition explicite du même nom n'est pas compatible avec l'instruction personnalisée fournie, une erreur QASM2ParseError sera levée. Ceci est utile pour la compatibilité avec d'anciens exportateurs OpenQASM 2 et avec certaines autres plateformes quantiques qui traitent les « portes de base » de leur matériel comme des instructions intégrées.

Qiskit fournit un attribut de données pour travailler avec des programmes OpenQASM 2 produits par des versions héritées des capacités d'export OpenQASM 2 de Qiskit. Il s'agit de qasm2.LEGACY_CUSTOM_INSTRUCTIONS, qui peut être passé comme argument custom_instructions à qasm2.load() et qasm2.loads().

Exemple : importer un programme créé par l'exportateur hérité de Qiskit

Ce programme OpenQASM 2 utilise des portes qui ne figurent pas dans la version originale de "qelib1.inc" sans les déclarer, mais qui sont des portes standard dans la bibliothèque de Qiskit. Tu peux utiliser qasm2.LEGACY_CUSTOM_INSTRUCTIONS pour indiquer facilement à l'importateur d'utiliser le même ensemble de portes que celui qu'utilisait précédemment l'exportateur OpenQASM 2 de Qiskit.

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

Exemple : utiliser une classe de porte particulière lors de l'import d'un programme OpenQASM 2

Qiskit ne peut pas, en général, vérifier si la définition dans une instruction gate OpenQASM 2 correspond exactement à une porte de la bibliothèque standard de Qiskit. À la place, Qiskit choisit une porte personnalisée en utilisant la définition exacte fournie. Cela peut être moins efficace qu'utiliser l'une des portes standard intégrées ou une porte personnalisée définie par l'utilisateur. Tu peux définir manuellement des instructions gate avec des classes particulières.

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

Exemple : définir une nouvelle porte intégrée dans un programme OpenQASM 2

Si l'argument builtin=True est défini, une porte personnalisée n'a pas besoin d'avoir de définition associée.

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

Définir des fonctions classiques personnalisées

OpenQASM 2 inclut certaines fonctions classiques intégrées à utiliser dans les arguments de portes. Tu peux étendre le langage avec davantage de fonctions en utilisant l'argument custom_classical de qasm2.load() et qasm2.loads(), avec la classe qasm2.CustomClassical.

Pour définir une fonction classique personnalisée, tu dois fournir :

  • Le nom de la fonction tel qu'il apparaît dans le programme OpenQASM 2
  • Le nombre d'arguments en virgule flottante qu'elle accepte
  • Un objet Python appelable qui évalue la fonction

Toutes les fonctions classiques personnalisées définies sont traitées comme intégrées au langage OpenQASM 2 par l'importateur. Il n'existe pas de méthode officielle dans le langage OpenQASM 2 pour définir de nouvelles fonctions ; il s'agit d'une extension Qiskit.

Exemple : utiliser des instructions classiques personnalisées

Nous fournissons ici deux fonctions classiques personnalisées. La première est simple et ajoute simplement un à son entrée. La seconde est la fonction math.atan2, qui représente l'opération mathématique arctan(y/x)\arctan(y/x) en tenant compte du quadrant.

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)

Mode strict

Par défaut, ce parseur est plus permissif que la spécification officielle. Il autorise les virgules de fin dans les listes de paramètres, les points-virgules superflus (instructions vides), l'omission de la déclaration de version OPENQASM 2.0;, ainsi que plusieurs autres améliorations pratiques, sans émettre d'erreurs. Cependant, tu peux utiliser le mode « lettre de la spécification » avec strict=True.

Exporter un circuit Qiskit vers OpenQASM 2

Qiskit peut également exporter un QuantumCircuit vers OpenQASM 2. Tu utilises la fonction qasm2.dump() pour écrire dans un fichier, et qasm2.dumps() pour écrire dans une chaîne de caractères. Ces fonctions ont actuellement une interface très simple : elles acceptent un circuit et, uniquement dans le cas de qasm2.dump(), un emplacement où écrire la sortie.

avertissement

L'exportateur OpenQASM 2 de Qiskit suppose toujours une version héritée et non standard du fichier d'inclusion "qelib1.inc". Ce problème sera résolu dans une prochaine version de Qiskit, mais en attendant, si tu dois réimporter un programme OpenQASM 2 créé avec Qiskit, utilise l'exemple ci-dessus pour indiquer à l'importateur les portes héritées.

Exemple : exporter un circuit vers 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")

Prochaines étapes

Recommandations