Zum Hauptinhalt springen

Estimator mit der REST API

Package versions

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

qiskit[all]~=2.3.0

Die Schritte in diesem Abschnitt 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 Estimator ein verwalteter Dienst ist, musst du zunächst dein Konto initialisieren. Danach kannst du das Gerät auswählen, das du zur Berechnung des Erwartungswerts verwenden möchtest.

Details zur Kontoinitialisierung, zum Anzeigen verfügbarer Backends und zum Ungültigmachen von Tokens findest du in diesem Abschnitt.

2. QASM-Circuit erstellen

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

Definiere einen QASM-Quantum-Circuit. Zum Beispiel:

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-Snippets gehen davon aus, dass qasm_string in einen neuen String resulting_qasm transpiliert wurde.

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

hinweis

Die folgenden Jobs verwenden Qiskit Runtime V2 Primitives. Sowohl SamplerV2 als auch EstimatorV2 nehmen 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, bei denen es sich um mehrere Observablen und Parameter handeln kann. Jeder PUB gibt ein Ergebnis 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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each.
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
}}

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-942fb30edcad
>>> Job Status: JobStatus.RUNNING

Job-Ergebnisse abrufen:

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

res_dict=response_result.json()

estimator_result=res_dict['results']
print(estimator_result)

Ausgabe

[{'data': {'evs': 0.7428980350102542, 'stds': 0.029884014518789213, 'ensemble_standard_error': 0.03261147170624149}, 'metadata': {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}}]

5. Mit 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 quantenspezifischem Vorverarbeitungs-Overhead beim Modelltraining und klassischem Nachverarbeitungs-Overhead, um Fehler in den Rohergebnissen mithilfe des generierten Modells zu mindern.

Die in Primitives integrierten Fehlerminderungstechniken sind erweiterte Resilience-Optionen. Um diese Optionen anzugeben, verwende die Option resilience_level beim Einreichen deines Jobs.

Die folgenden Beispiele zeigen die Standardoptionen für Dynamical Decoupling, Twirling und TREX + ZNE. Weitere Optionen und Details findest du im Abschnitt Fehlerminderungs- und Unterdrückungstechniken.

TREX + ZNE

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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"options": {
"resilience": {
"measure_mitigation": True,
"zne_mitigation": True,
"zne": {
"extrapolator":["exponential", "linear"],
"noise_factors":[1, 3, 5],
},
},
},
}
}

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}")

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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"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. Danach kannst du das Gerät auswählen, auf dem du deine Berechnungen ausführen möchtest.

Details zur Kontoinitialisierung, zum Anzeigen verfügbarer Backends und zum Ungültigmachen von Tokens findest du in diesem Abschnitt.

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')
parameter_values = {'theta': 1.57, 'phi': 3.14} # In case we want to pass a dictionary

3. 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. Quantum-Circuit mit der Estimator 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': 'estimator',
"backend": backend,
"params": {
# Choose one option: direct parameter transfer or through a dictionary
#"pubs": [[qasm_str,[1,2],500]], # primitive unified blocs (PUBs) containing one circuit each.
"pubs": [[qasm_str,parameter_values,500]], # primitive unified blocs (PUBs) containing one circuit each.
}}

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 mehrere Möglichkeiten, Workloads auszuführen, je nach deinen Anforderungen: Job-Modus, Session-Modus und Batch-Modus. Wie du mit dem Session-Modus und dem Batch-Modus arbeitest, erfährst du im Abschnitt zu Ausführungsmodi. Beachte, dass Nutzer des Open Plan keine Session-Jobs einreichen können.
  • Erfahre, wie du dein Konto initialisierst mit REST API.
  • Übe mit Primitives anhand der Lektion zu Kostenfunktionen im IBM Quantum® Learning.
  • Erfahre, wie du lokal transpilierst, im Abschnitt Transpile.