OpenQASM 2 und das Qiskit SDK
Paketversionen
Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen die Verwendung dieser oder neuerer Versionen.
qiskit[all]~=2.3.0
Das Qiskit SDK bietet einige Tools zur Konvertierung zwischen OpenQASM-Darstellungen von Quantenprogrammen und der QuantumCircuit-Klasse.
Importieren eines OpenQASM 2-Programms in Qiskit
Zwei Funktionen importieren OpenQASM 2-Programme in Qiskit.
Dies sind qasm2.load(), die einen Dateinamen akzeptiert, und qasm2.loads(), die das OpenQASM 2-Programm als String akzeptiert.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
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)
Weitere Informationen findest du in der OpenQASM 2 Qiskit API.
Importieren einfacher Programme
Für die meisten OpenQASM 2-Programme kannst du einfach qasm2.load und qasm2.loads mit einem einzigen Argument verwenden.
Beispiel: Importieren eines OpenQASM 2-Programms als String
Verwende qasm2.loads(), um ein OpenQASM 2-Programm als String in einen QuantumCircuit zu importieren:
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
Beispiel: Importieren eines OpenQASM 2-Programms aus einer Datei
Verwende load(), um ein OpenQASM 2-Programm aus einer Datei in einen QuantumCircuit zu importieren:
import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")
Verknüpfen von OpenQASM 2-Gates mit Qiskit-Gates
Standardmäßig behandelt der OpenQASM 2-Importer von Qiskit die Include-Datei "qelib1.inc" als de facto Standardbibliothek.
Der Importer behandelt diese Datei so, als enthielte sie genau die Gates, die in dem ursprünglichen Papier, das OpenQASM 2 definiert, beschrieben sind.
Qiskit verwendet die integrierten Gates in der Circuit Library, um die Gates in "qelib1.inc" darzustellen.
Gates, die im Programm durch manuelle OpenQASM 2 gate-Anweisungen definiert werden, werden standardmäßig als benutzerdefinierte Qiskit Gate-Unterklassen konstruiert.
Du kannst dem Importer mitteilen, spezifische Gate-Klassen für die von ihm gefundenen gate-Anweisungen zu verwenden.
Du kannst diesen Mechanismus auch verwenden, um zusätzliche Gate-Namen als "built-in" zu behandeln, d.h. keine explizite Definition zu erfordern.
Wenn du angibst, welche Gate-Klassen für gate-Anweisungen außerhalb von "qelib1.inc" verwendet werden sollen, ist die resultierende Schaltung typischerweise effizienter zu bearbeiten.
Ab Qiskit SDK v1.0 verhält sich der OpenQASM 2-Exporter von Qiskit (siehe Exportieren einer Qiskit-Schaltung nach OpenQASM 2) immer noch so, als hätte "qelib1.inc" mehr Gates als tatsächlich vorhanden sind.
Das bedeutet, dass die Standardeinstellungen des Importers möglicherweise kein von unserem Exporter exportiertes Programm importieren können.
Siehe das spezifische Beispiel zur Arbeit mit dem Legacy-Exporter, um dieses Problem zu lösen.
Dies ist Legacy-Verhalten von Qiskit, und es wird in einer späteren Version von Qiskit behoben.
Um Informationen über eine benutzerdefinierte Anweisung an den OpenQASM 2-Importer zu übergeben, verwende die qasm2.CustomInstruction-Klasse.
Diese hat vier erforderliche Informationen, in dieser Reihenfolge:
- Der Name des Gates, der im OpenQASM 2-Programm verwendet wird
- Die Anzahl der Winkelparameter, die das Gate akzeptiert
- Die Anzahl der Qubits, auf die das Gate wirkt
- Die Python-Konstruktor-Klasse oder -Funktion für das Gate, die die Gate-Parameter (aber nicht die Qubits) als einzelne Argumente akzeptiert
Wenn der Importer auf eine gate-Definition trifft, die mit einer gegebenen benutzerdefinierten Anweisung übereinstimmt, wird er diese benutzerdefinierten Informationen verwenden, um das Gate-Objekt zu rekonstruieren.
Wenn eine gate-Anweisung gefunden wird, die mit dem name einer benutzerdefinierten Anweisung übereinstimmt, aber nicht sowohl mit der Anzahl der Parameter als auch mit der Anzahl der Qubits übereinstimmt, gibt der Importer einen QASM2ParseError aus, um die Diskrepanz zwischen den bereitgestellten Informationen und dem Programm anzuzeigen.
Zusätzlich kann ein fünftes Argument builtin optional auf True gesetzt werden, um das Gate automatisch innerhalb des OpenQASM 2-Programms verfügbar zu machen, auch wenn es nicht explizit definiert ist.
Wenn der Importer auf eine explizite gate-Definition für eine integrierte benutzerdefinierte Anweisung trifft, wird er sie stillschweigend akzeptieren.
Wie zuvor wird ein QASM2ParseError ausgegeben, wenn eine explizite Definition desselben Namens nicht mit der bereitgestellten benutzerdefinierten Anweisung kompatibel ist.
Dies ist nützlich für die Kompatibilität mit älteren OpenQASM 2-Exportern und mit bestimmten anderen Quantenplattformen, die die "Basis-Gates" ihrer Hardware als integrierte Anweisungen behandeln.
Qiskit bietet ein Datenattribut für die Arbeit mit OpenQASM 2-Programmen, die von Legacy-Versionen von Qiskits OpenQASM 2-Exportfunktionen erstellt wurden.
Dies ist qasm2.LEGACY_CUSTOM_INSTRUCTIONS, das als custom_instructions-Argument an qasm2.load() und qasm2.loads() übergeben werden kann.
Beispiel: Importieren eines Programms, das vom Legacy-Exporter von Qiskit erstellt wurde
Dieses OpenQASM 2-Programm verwendet Gates, die nicht in der ursprünglichen Version von "qelib1.inc" enthalten sind, ohne sie zu deklarieren, aber Standard-Gates in Qiskits Bibliothek sind.
Du kannst qasm2.LEGACY_CUSTOM_INSTRUCTIONS verwenden, um dem Importer einfach mitzuteilen, dass er denselben Satz von Gates verwenden soll, den Qiskits OpenQASM 2-Exporter zuvor verwendet hat.
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,
)
Beispiel: Verwendung einer bestimmten Gate-Klasse beim Importieren eines OpenQASM 2-Programms
Qiskit kann im Allgemeinen nicht überprüfen, ob die Definition in einer OpenQASM 2 gate-Anweisung genau einem Gate der Qiskit-Standardbibliothek entspricht.
Stattdessen wählt Qiskit ein benutzerdefiniertes Gate unter Verwendung der bereitgestellten genauen Definition.
Dies kann weniger effizient sein als die Verwendung eines der integrierten Standard-Gates oder eines benutzerdefinierten Gates.
Du kannst manuell gate-Anweisungen mit bestimmten Klassen definieren.
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,
)
Beispiel: Definieren eines neuen integrierten Gates in einem OpenQASM 2-Programm
Wenn das Argument builtin=True gesetzt ist, benötigt ein benutzerdefiniertes Gate keine zugehörige Definition.
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,
)
Definieren benutzerdefinierter klassischer Funktionen
OpenQASM 2 enthält einige integrierte klassische Funktionen zur Verwendung in Gate-Argumenten.
Du kannst die Sprache mit weiteren Funktionen erweitern, indem du das custom_classical-Argument für qasm2.load() und qasm2.loads() mit der qasm2.CustomClassical-Klasse verwendest.
Um eine benutzerdefinierte klassische Funktion zu definieren, musst du Folgendes angeben:
- Den Namen der Funktion, wie er im OpenQASM 2-Programm erscheint
- Die Anzahl der Gleitkomma-Argumente, die sie akzeptiert
- Ein aufrufbares Python-Objekt, das die Funktion auswertet
Alle definierten benutzerdefinierten klassischen Funktionen werden vom Importer als in die OpenQASM 2-Sprache integriert behandelt. Es gibt keine offizielle Möglichkeit innerhalb der OpenQASM 2-Sprache, neue Funktionen zu definieren; dies ist eine Qiskit-Erweiterung.
Beispiel: Verwendung benutzerdefinierter klassischer Anweisungen
Hier stellen wir zwei benutzerdefinierte klassische Funktionen bereit.
Die erste ist einfach und fügt ihrem Eingabewert einfach eins hinzu.
Die zweite ist die Funktion math.atan2, die die mathematische Operation quadrantengerecht darstellt.
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)
Strict-Modus
Standardmäßig ist dieser Parser entspannter als die offizielle Spezifikation.
Er erlaubt nachfolgende Kommas in Parameterlisten; unnötige (Leer-Statement-)Semikolons; Weglassen der OPENQASM 2.0;-Versionsanweisung; und mehrere andere Qualitätsverbesserungen ohne Ausgabe von Fehlern.
Du kannst jedoch den "buchstabengetreuen" Modus mit strict=True verwenden.
Exportieren einer Qiskit-Schaltung nach OpenQASM 2
Qiskit kann auch einen QuantumCircuit nach OpenQASM 2 exportieren.
Du verwendest die Funktion qasm2.dump(), um in eine Datei zu schreiben, und qasm2.dumps(), um in einen String zu schreiben.
Diese Funktionen haben derzeit eine sehr einfache Schnittstelle: Sie akzeptieren eine Schaltung und, nur im Fall von qasm2.dump(), einen Ort, an den die Ausgabe geschrieben werden soll.
Qiskits OpenQASM 2-Exporter geht immer noch von einer Legacy-, nicht standardmäßigen Version der "qelib1.inc"-Include-Datei aus.
Dies wird in einer späteren Version von Qiskit behoben, aber in der Zwischenzeit, wenn du ein mit Qiskit erstelltes OpenQASM 2-Programm erneut importieren musst, verwende das obige Beispiel dafür, wie du dem Importer über die Legacy-Gates mitteilst.
Beispiel: Exportieren einer Schaltung nach 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")
Nächste Schritte
- Erfahre, wie du OpenQASM-Code im Leitfaden IBM Quantum Composer generierst.
- Siehe die OpenQASM 2 Qiskit API-Referenz.
- Lies das Thema Überprüfe dein Programm.
- Besuche die OpenQASM Live Specification.