Zum Hauptinhalt springen

Schreib dein erstes Qiskit Serverless-Programm

Paketversionen

Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen, diese Versionen oder neuere zu verwenden.

qiskit[all]~=1.3.1
qiskit-ibm-runtime~=0.34.0
qiskit-aer~=0.15.1
qiskit-serverless~=0.18.1
qiskit-ibm-catalog~=0.2
qiskit-addon-sqd~=0.8.1
qiskit-addon-utils~=0.1.0
qiskit-addon-mpf~=0.2.0
qiskit-addon-aqc-tensor~=0.1.2
qiskit-addon-obp~=0.1.0
scipy~=1.15.0
pyscf~=2.8.0
tipp

Qiskit Serverless wird gerade aufgerüstet, und seine Funktionen ändern sich schnell. Während dieser Entwicklungsphase findest du Release Notes und die aktuellste Dokumentation auf der Qiskit Serverless GitHub-Seite.

Dieses Beispiel zeigt, wie du qiskit-serverless-Tools verwendest, um ein paralleles Transpilierungsprogramm zu erstellen, und anschließend qiskit-ibm-catalog einsetzt, um dein Programm auf IBM Quantum Platform hochzuladen und als wiederverwendbaren Remote-Dienst zu nutzen.

Workflow-Überblick

  1. Erstelle ein lokales Verzeichnis und eine leere Programmdatei (./source_files/transpile_remote.py)
  2. Füge deiner Programmdatei Code hinzu, der nach dem Hochladen auf Qiskit Serverless einen Circuit transpiliert
  3. Verwende qiskit-ibm-catalog, um dich bei Qiskit Serverless zu authentifizieren
  4. Lade das Programm auf Qiskit Serverless hoch

Nachdem du dein Programm hochgeladen hast, kannst du es ausführen, um den Circuit zu transpilieren – folge dazu der Anleitung Führe deine erste Qiskit Serverless-Arbeitslast remote aus.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-catalog qiskit-ibm-runtime qiskit-serverless

Beispiel: Remote-Transpilierung mit Qiskit Serverless

Dieses Beispiel führt dich durch das Erstellen und Befüllen einer Programmdatei, die – nach dem Hochladen auf Qiskit Serverless – einen circuit gegen ein gegebenes backend und einen Ziel-optimization_level transpiliert.

tipp

Qiskit Serverless erfordert, dass du die .py-Dateien deiner Arbeitslast in einem eigenen Verzeichnis organisierst. Die folgende Struktur ist ein Beispiel für gute Praxis:

serverless_program
├── program_uploader.ipynb
└── source_files
├── transpile_remote.py
└── *.py

Serverless lädt den Inhalt eines bestimmten Verzeichnisses (in diesem Beispiel das Verzeichnis source_files) hoch, um ihn remote auszuführen. Nachdem du das eingerichtet hast, kannst du transpile_remote.py anpassen, um Eingaben abzurufen und Ausgaben zurückzugeben.

Verzeichnis und leere Programmdatei erstellen

Erstelle zunächst ein Verzeichnis namens source_files und dann eine Programmdatei darin, sodass ihr Pfad ./source_files/transpile_remote.py lautet. Das ist die Datei, die du auf Qiskit Serverless hochladen wirst.

Code zur Programmdatei hinzufügen

Befülle deine Programmdatei mit dem folgenden Code und speichere sie anschließend.

vorsicht

Wenn du die Code-Zellen lokal in einem Notebook liest, siehst du den %%writefile-Magic Command. Das Ausführen von Zellen mit diesem Magic Command speichert sie auf dem Datenträger, anstatt sie auszuführen.

# This cell is hidden from users, it creates a new folder
from pathlib import Path

Path("./source_files").mkdir(exist_ok=True)
%%writefile ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit.transpiler import generate_preset_pass_manager

def transpile_remote(circuit, optimization_level, backend):
"""Transpiles an abstract circuit into an ISA circuit for a given backend."""
pass_manager = generate_preset_pass_manager(
optimization_level=optimization_level,
backend=backend
)
isa_circuit = pass_manager.run(circuit)
return isa_circuit

Code zum Abrufen der Programmargumente hinzufügen

Füge nun den folgenden Code zu deiner Programmdatei hinzu, der die Programmargumente einrichtet.

Deine initiale transpile_remote.py hat drei Eingaben: circuits, backend_name und optimization_level. Serverless ist derzeit darauf beschränkt, nur serialisierbare Eingaben und Ausgaben zu akzeptieren. Aus diesem Grund kannst du backend nicht direkt übergeben – verwende stattdessen backend_name als String.

%%writefile --append ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit_serverless import get_arguments, save_result, distribute_task, get

# Get program arguments
arguments = get_arguments()
circuits = arguments.get("circuits")
backend_name = arguments.get("backend_name")
optimization_level = arguments.get("optimization_level")

Code zum Aufrufen des Backends hinzufügen

Füge den folgenden Code zu deiner Programmdatei hinzu, der dein Backend mit QiskitRuntimeService aufruft.

Der folgende Code setzt voraus, dass du bereits deine Anmeldedaten mit QiskitRuntimeService.save_account gespeichert hast, und lädt dein standardmäßig gespeichertes Konto, sofern du nichts anderes angibst. Weitere Informationen findest du unter Anmeldedaten speichern und Deinen Qiskit Runtime-Dienst-Account initialisieren.

%%writefile --append ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.backend(backend_name)

Code zur Transpilierung hinzufügen

Füge schließlich den folgenden Code zu deiner Programmdatei hinzu. Dieser Code führt transpile_remote() für alle übergebenen circuits aus und gibt die transpiled_circuits als Ergebnis zurück:

%%writefile --append ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

# Each circuit is being transpiled and will populate the array
results = [
transpile_remote(circuit, 1, backend)
for circuit in circuits
]

save_result({
"transpiled_circuits": results
})

Bei Qiskit Serverless authentifizieren

Verwende qiskit-ibm-catalog, um dich mit deinem API-Schlüssel bei QiskitServerless zu authentifizieren (du kannst deinen QiskitRuntimeService-API-Schlüssel verwenden oder einen neuen API-Schlüssel im IBM Quantum Platform-Dashboard erstellen).

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction

# Authenticate to the remote cluster and submit the pattern for remote execution
serverless = QiskitServerless()

Code zum Hochladen ausführen

Führe den folgenden Code aus, um das Programm hochzuladen. Qiskit Serverless komprimiert den Inhalt von working_dir (in diesem Fall source_files) in ein tar-Archiv, das hochgeladen und anschließend bereinigt wird. Der entrypoint gibt die ausführbare Hauptprogrammdatei an, die Qiskit Serverless ausführen soll.

transpile_remote_demo = QiskitFunction(
title="transpile_remote_serverless",
entrypoint="transpile_remote.py",
working_dir="./source_files/",
)
serverless.upload(transpile_remote_demo)
QiskitFunction(transpile_remote_serverless)

Upload überprüfen

Um zu prüfen, ob der Upload erfolgreich war, verwende serverless.list(), wie im folgenden Code:

# Get program from serverless.list() that matches the title of the one we uploaded
next(
program
for program in serverless.list()
if program.title == "transpile_remote_serverless"
)
QiskitFunction(transpile_remote_serverless)
# This cell is hidden from users, it checks the program uploaded correctly
assert _.title == "transpile_remote_serverless" # noqa: F821
# This cell is hidden from users, it checks the program executes correctly
from time import sleep
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
transpile_remote_serverless = serverless.load("transpile_remote_serverless")
job = transpile_remote_serverless.run(
circuits=[qc],
backend="ibm_sherbrooke",
optimization_level=1,
)
while True:
sleep(5)
status = job.status()
if status not in ["QUEUED", "INITIALIZING", "RUNNING", "DONE"]:
raise Exception(
f"Unexpected job status: '{status}'\n"
+ "Here are the logs:\n"
+ job.logs()
)
if status == "DONE":
break

Nächste Schritte

Empfehlungen