Zum Hauptinhalt springen

Schreibe dein erstes Qiskit Serverless-Programm

Paketversionen

Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen, diese oder neuere Versionen 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

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 der IBM Quantum Platform als wiederverwendbaren Remote-Dienst bereitzustellen.

Beispiel: Remote-Transpilierung mit Qiskit Serverless

Beginne mit dem folgenden Beispiel, das einen circuit für ein gegebenes backend und einen Ziel-optimization_level transpiliert, und füge schrittweise weitere Elemente hinzu, um deine Arbeitslast in Qiskit Serverless bereitzustellen.

Füge den folgenden Code in die Datei ./source_files/transpile_remote.py ein. Diese Datei ist das Programm, das du in Qiskit Serverless hochlädst.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-catalog qiskit-ibm-runtime qiskit-serverless
# This cell is hidden from users, it just creates a new folder
from pathlib import Path

Path("./source_files").mkdir(exist_ok=True)
%%writefile ./source_files/transpile_remote.py

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
Writing ./source_files/transpile_remote.py

Dateien einrichten

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 von source_files hoch, um ihn remote auszuführen. Sobald diese Dateien eingerichtet sind, kannst du transpile_remote.py anpassen, um Eingaben entgegenzunehmen und Ausgaben zurückzugeben.

Programmargumente abrufen

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

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")
Appending to ./source_files/transpile_remote.py

An diesem Punkt kannst du dein Backend mit QiskitRuntimeService abrufen und dein vorhandenes Programm mit dem folgenden Code ergänzen. Der folgende Code setzt voraus, dass du deine Zugangsdaten bereits gespeichert hast.

%%writefile --append ./source_files/transpile_remote.py

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.backend(backend_name)
Appending to ./source_files/transpile_remote.py

Schließlich kannst du transpile_remote() für alle übergebenen circuits ausführen und die transpiled_circuits als Ergebnis zurückgeben:

%%writefile --append ./source_files/transpile_remote.py

results = [
transpile_remote(circuit, 1, backend)
for circuit in circuits
]

save_result({
"transpiled_circuits": results
})
Appending to ./source_files/transpile_remote.py

Auf der IBM Quantum Platform bereitstellen

Im vorherigen Abschnitt wurde ein Programm erstellt, das remote ausgeführt werden soll. Die Code-Zellen in diesem Abschnitt laden dieses Programm in Qiskit Serverless hoch.

Verwende qiskit-ibm-catalog, um dich mit deinem API-Schlüssel bei QiskitServerless zu authentifizieren. Den API-Schlüssel findest du im IBM Quantum Dashboard. Lade anschließend das Programm hoch.

Du kannst save_account() verwenden, um deine Zugangsdaten zu speichern (siehe Abschnitt Einrichtung für IBM Cloud). Beachte, dass dabei deine Zugangsdaten in dieselbe Datei geschrieben werden wie bei QiskitRuntimeService.save_account().

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction

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

Qiskit Serverless komprimiert den Inhalt von working_dir (in diesem Fall source_files) in ein tar-Archiv, das hochgeladen und danach bereinigt wird. Der entrypoint identifiziert die ausführbare Hauptprogrammdatei, die Qiskit Serverless ausführen soll. Falls dein Programm benutzerdefinierte pip-Abhängigkeiten hat, kannst du diese in einem dependencies-Array angeben:

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)

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

# 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