Zum Hauptinhalt springen

Sampler mit der REST API

Die Schritte in diesem Thema beschreiben, wie du Workloads mit der REST API ausführst und konfigurierst, und zeigen, wie du sie in einem beliebigen Programm deiner Wahl aufrufst.

hinweis

Diese Dokumentation verwendet das Python-Modul requests, um die Qiskit Runtime REST API zu demonstrieren. Dieser Workflow kann jedoch mit jeder Sprache oder jedem Framework ausgeführt werden, das die Arbeit mit REST APIs unterstützt. Weitere Details findest du in der API-Referenzdokumentation.

1. Konto initialisieren

Da der Qiskit Runtime Sampler ein verwalteter Dienst ist, musst du zunächst dein Konto initialisieren. Du kannst dann das Gerät auswählen, auf dem du deine Berechnungen ausführen möchtest.

Details zur Initialisierung deines Kontos, zur Anzeige verfügbarer Backends und zur Arbeit mit Tokens findest du unter Einrichtung für die Verwendung von IBM Quantum Platform mit REST API.

2. Einen QASM-Circuit erstellen

Du benötigst mindestens einen Circuit als Eingabe für das Sampler-Primitive.

Definiere einen QASM-Quantum-Circuit:

qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''

Die folgenden Code-Ausschnitte setzen voraus, dass der qasm_string in einen neuen String resulting_qasm transpiliert wurde.

3. Den Quantum-Circuit mit der Sampler V2 API ausführen

hinweis

Die nachfolgenden Jobs verwenden Qiskit Runtime V2-Primitive. SamplerV2 nimmt einen oder mehrere Primitive Unified Blocs (PUBs) als Eingabe entgegen. Jeder PUB ist ein Tupel, das einen Circuit und die an diesen Circuit übertragenen Daten enthält – das können mehrere Parameter sein –, und gibt ein Ergebnis pro PUB zurück.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm],[resulting_qasm,None,500]]
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

4. Job-Status prüfen und Ergebnisse abrufen

Übergib als Nächstes die job_id an die API:

response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')

Ausgabe

>>> Job ID: 58223448-5100-4dec-a47a-942fb30edced
>>> Job Status: JobStatus.RUNNING

Job-Ergebnisse abrufen:

response_result= requests.get(url+'/'+job_id+'/results', headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])

Ausgabe

['0x3', '0x0', '0x2', '0x1', '0x0', '0x3', '0x0', '0x3', '0x1', '0x2', '0x2', '0x0', '0x2', '0x0', '0x3', '0x3', '0x2', '0x0', '0x1', '0x0']

5. Mit Qiskit Runtime-Optionen arbeiten

Fehlerminderungstechniken ermöglichen es Nutzern, Circuit-Fehler zu reduzieren, indem das Geräterauschen zum Zeitpunkt der Ausführung modelliert wird. Dies führt typischerweise zu Overhead bei der Quantenvorverarbeitung im Zusammenhang mit dem Modelltraining sowie zu Overhead bei der klassischen Nachverarbeitung, um Fehler in den Rohergebnissen mithilfe des generierten Modells zu reduzieren.

Die in Primitive integrierten Fehlerminderungstechniken sind erweiterte Resilienzoptionen. Um diese Optionen anzugeben, verwende die Option resilience_level beim Einreichen deines Jobs. Sampler V2 unterstützt keine Angabe von Resilienzstufen. Du kannst jedoch einzelne Fehlerminderungs-/Unterdrückungsmethoden ein- oder ausschalten.

Die folgenden Beispiele zeigen die Standardoptionen für Dynamical Decoupling und Twirling. Weitere Optionen und Details findest du im Thema Fehlerminderungs- und Fehlerunterdrückungstechniken.

Dynamical Decoupling

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm]],
"options": {
"dynamical_decoupling": {
"enable": True,
"sequence_type": 'XpXm',
"extra_slack_distribution": 'middle',
"scheduling_method": 'alap',
},
},
}
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

Twirling

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm]],
"options": {
"twirling": {
"enable_gates": True,
"enable_measure": True,
"num_randomizations": "auto",
"shots_per_randomization": "auto",
"strategy": "active-accum",
},
},
}
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

Parametrisierte Circuits

1. Konto initialisieren

Da Qiskit Runtime ein verwalteter Dienst ist, musst du zunächst dein Konto initialisieren. Du kannst dann das Gerät auswählen, auf dem du deine Berechnungen ausführen möchtest.

Details zur Initialisierung deines Kontos, zur Anzeige verfügbarer Backends und zur Invalidierung von Tokens findest du in diesem Thema.

2. Parameter definieren

import requests
import qiskit_ibm_runtime
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.qasm3 import dumps
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit import transpile

service = QiskitRuntimeService(channel='ibm_quantum')
backend = service.backend("<SPECIFY BACKEND>")

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)

theta = Parameter('theta')
phi = Parameter('phi')
# In case we want to pass a dictionary:
parameter_values = {'theta': 1.57, 'phi': 3.14}

3. Einen Quantum-Circuit erstellen und parametrisierte Gates hinzufügen

qc = QuantumCircuit(2)

# Add parameterized gates
qc.rx(theta, 0)
qc.ry(phi, 1)
qc.cx(0, 1)
qc.measure_all()

# Draw the original circuit
qc.draw('mpl')

# Get an ISA circuit
isa_circuit = pm.run(qc)

4. QASM-3-Code generieren

qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)

5. Den Quantum-Circuit mit der Sampler V2 API ausführen

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}

job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# Choose one option: direct parameter transfer or through a dictionary
# # primitive unified blocs (PUBs) containing one circuit each:
#"pubs": [[qasm_str,[1,2],500]],

# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[qasm_str,parameter_values,500]],
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print(f"Job created: {response.text}")
else:
print(f"Error: {response.status_code}")
print(response.text)

6. Job-Status prüfen und Ergebnisse abrufen

Übergib als Nächstes die job_id an die API:

response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')

Ausgabe

{'status': 'Completed'}

Job-Ergebnisse abrufen:

response_result = requests.get(f"{url}/{job_id}/results", headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])

Ausgabe

['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']

Nächste Schritte

Empfehlungen
  • Es gibt verschiedene Möglichkeiten, Workloads auszuführen, je nach deinen Anforderungen: Job-Modus, Session-Modus und Batch-Modus. Erfahre, wie du mit dem Session-Modus und dem Batch-Modus arbeitest, im Thema zu Ausführungsmodi. Beachte, dass Nutzer des Open Plans keine Session-Jobs einreichen können.
  • Erfahre, wie du dein Konto initialisierst mit der REST API.
  • Übe mit Primitiven durch die Kostenfunktions-Lektion in IBM Quantum Learning.
  • Erfahre, wie du lokal transpilierst, im Abschnitt Transpile.