OpenQASM 2 und das Qiskit SDK
Paketversionen
Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen, diese Versionen oder neuere zu verwenden.
qiskit[all]~=2.5.2
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
Das Qiskit SDK bietet einige Tools zur Umwandlung zwischen OpenQASM-Darstellungen von Quantenprogrammen und der Klasse QuantumCircuit.
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.
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 der Originalveröffentlichung zu OpenQASM 2 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.
Diese Diskrepanz ist ein Altverhalten von Qiskit, und sie wird in einer späteren Version von Qiskit behoben.
Um Informationen über eine benutzerdefinierte Instruktion an den OpenQASM 2-Importer zu übergeben, verwende die qasm2.CustomInstruction-Klasse.
Diese hat vier erforderliche Angaben, 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 Instruktion ü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 Instruktion übereinstimmt, aber nicht sowohl mit der Anzahl der Parameter als auch mit der Anzahl der Qubits übereinstimmt, löst 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 Instruktion trifft, wird er sie stillschweigend akzeptieren.
Wie zuvor wird ein QASM2ParseError ausgelöst, wenn eine explizite Definition desselben Namens nicht mit der bereitgestellten benutzerdefinierten Instruktion 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 Instruktionen 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 automatisch erzeugtes Custom-Gate unter Verwendung der bereitgestellten genauen Definition.
Dies kann weniger effizient sein als die Verwendung eines der integrierten Standard-Gates oder eines vom Benutzer definierten 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 Instruktionen
Hier stellen wir zwei benutzerdefinierte klassische Funktionen bereit.
Die erste ist simpel: Sie addiert einfach eins zu ihrem Eingabewert.
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 weniger streng als die offizielle Spezifikation.
Er erlaubt abschließende Kommas in Parameterlisten; unnötige (Leer-Statement-)Semikolons; Weglassen der OPENQASM 2.0;-Versionsanweisung; sowie einige weitere Erleichterungen, ohne Fehler auszugeben.
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 veralteten, nicht standardkonformen Version der "qelib1.inc"-Include-Datei aus.
Dies wird in einer späteren Version von Qiskit behoben. Bis dahin gilt: Wenn du ein mit Qiskit erstelltes OpenQASM 2-Programm erneut importieren musst, verwende das obige Beispiel dafür, wie du den Importer über die Legacy-Gates informierst.
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.