Sari la conținutul principal

QESEM: O Funcție Qiskit de Qedma

Consultă referința API

Versiuni de pachete

Codul de pe această pagină a fost dezvoltat folosind următoarele cerințe. Recomandăm folosirea acestor versiuni sau a unora mai noi.

qiskit[all]~=2.5.0
qiskit-ibm-runtime~=0.47.0
Notă

Funcțiile Qiskit sunt o funcționalitate experimentală disponibilă doar utilizatorilor din planurile IBM Quantum® Premium, Flex și On-Prem (prin API-ul IBM Quantum Platform). Acestea se află în stadiu de previzualizare și pot suferi modificări.

Prezentare generală​

Deși unitățile de procesare cuantică s-au îmbunătățit considerabil în ultimii ani, erorile cauzate de zgomot și imperfecțiunile hardware-ului existent rămân o provocare centrală pentru dezvoltatorii de algoritmi cuantici. Pe măsură ce domeniul se apropie de calcule cuantice la scară utilitară care nu pot fi verificate clasic, soluțiile pentru eliminarea zgomotului cu acuratețe garantată devin din ce în ce mai importante. Pentru a depăși această provocare, Qedma a dezvoltat Quantum Error Mitigation (QESEM), integrat fără întreruperi pe IBM Quantum Platform ca Funcție Qiskit.

Cu QESEM, utilizatorii pot rula circuitele lor cuantice pe QPU-uri cu zgomot pentru a obține rezultate precise, fără erori, cu costuri de timp QPU extrem de eficiente, aproape de limitele fundamentale. Pentru a realiza acest lucru, QESEM utilizează o suită de metode proprietare dezvoltate de Qedma pentru caracterizarea și reducerea erorilor. Tehnicile de reducere a erorilor includ optimizarea porților, transpilarea conștientă de zgomot, suprimarea erorilor (ES) și atenuarea nebiasată a erorilor (EM). Prin această combinație de metode bazate pe caracterizare, utilizatorii pot obține rezultate fiabile, fără erori, pentru circuite cuantice generice de volum mare, deblocând aplicații care nu ar putea fi realizate altfel.

Pentru o descriere completă a componentelor de bază, precum și o demonstrație la scară utilitară, consultați articolul Reliable high-accuracy error mitigation for utility-scale quantum circuits.

Descriere​

Poți folosi funcția QESEM de Qedma pentru a estima și executa cu ușurință circuitele tale cu suprimare și atenuare a erorilor, obținând volume de circuit mai mari și acuratețe superioară. Pentru a utiliza QESEM, furnizezi un circuit cuantic, un set de observabile de măsurat, o acuratețe statistică țintă pentru fiecare observabilă și un QPU ales. Înainte de a rula circuitul la acuratețea țintă, poți estima timpul QPU necesar pe baza unui calcul analitic care nu necesită execuția circuitului. Odată ce ești mulțumit de estimarea timpului QPU, poți executa circuitul cu QESEM.

Când execuți un circuit, QESEM rulează un protocol de caracterizare a dispozitivului adaptat circuitului tău, producând un model de zgomot fiabil pentru erorile care apar în circuit. Pe baza caracterizării, QESEM implementează mai întâi transpilarea conștientă de zgomot pentru a mapa circuitul de intrare pe un set de qubiți și porți fizice, minimizând zgomotul care afectează observabila țintă. Acestea includ porțile disponibile nativ (CX/CZ pe dispozitivele IBM®), precum și porți suplimentare optimizate de QESEM, formând setul extins de porți al QESEM. QESEM rulează apoi un set de circuite ES și EM bazate pe caracterizare pe QPU și colectează rezultatele măsurătorilor acestora. Acestea sunt apoi post-procesate clasic pentru a furniza o valoare de așteptare nebiasată și o marjă de eroare pentru fiecare observabilă, corespunzătoare acurateței solicitate.

Prezentare generală Qedma QESEM S-a demonstrat că QESEM oferă rezultate cu acuratețe ridicată pentru o varietate de aplicații cuantice și pe cele mai mari volume de circuit realizabile astăzi. QESEM oferă următoarele funcționalități orientate către utilizator, demonstrate în secțiunea de benchmark-uri de mai jos:

  • Acuratețe garantată: QESEM produce estimări nebiasate pentru valorile de așteptare ale observabilelor. Metoda sa EM este echipată cu garanții teoretice care — împreună cu caracterizarea de ultimă generație a Qedma — asigură că atenuarea converge către ieșirea circuitului fără zgomot, cu o acuratețe specificată de utilizator. Spre deosebire de multe metode EM euristice predispuse la erori sistematice sau biasuri, acuratețea garantată a QESEM este esențială pentru asigurarea unor rezultate fiabile în circuite și observabile cuantice generice.
  • Scalabilitate pe QPU-uri mari: Timpul QPU al QESEM depinde de volumele circuitelor, dar este altfel independent de numărul de qubiți. Qedma a demonstrat QESEM pe cele mai mari dispozitive cuantice disponibile astăzi, inclusiv dispozitivele IBM Quantum Eagle de 127 qubiți și Heron de 133 qubiți.
  • Independent de aplicație: QESEM a fost demonstrat pe o varietate de aplicații, inclusiv simulare Hamiltoniană, VQE, QAOA și estimare de amplitudine. Utilizatorii pot introduce orice circuit cuantic și observabilă de măsurat și pot obține rezultate precise, fără erori. Singurele limitări sunt dictate de specificațiile hardware-ului și de timpul QPU alocat, care determină volumele de circuit accesibile și acuratețele ieșirii. Spre deosebire de aceasta, multe soluții de reducere a erorilor sunt specifice aplicației sau implică euristici necontrolate, ceea ce le face inaplicabile pentru circuite și aplicații cuantice generice.
  • Set extins de porți: QESEM suportă porți cu unghiuri fracționare și furnizează porți Rzz(θ)Rzz(\theta) cu unghiuri fracționare optimizate de Qedma pe dispozitivele IBM Quantum Heron și Eagle. Acest set extins de porți permite o compilare mai eficientă și deblochează volume de circuit mai mari cu un factor de până la 2 față de compilarea implicită CX/CZ.
  • Observabile multibase: QESEM suportă observabile de intrare compuse din mai multe șiruri Pauli necomutante, cum ar fi Hamiltonieni generici. Alegerea bazelor de măsurare și optimizarea alocării resurselor QPU (shot-uri și circuite) sunt apoi efectuate automat de QESEM pentru a minimiza timpul QPU necesar la acuratețea solicitată. Această optimizare, care ține cont de fidelitățile hardware-ului și de ratele de execuție, îți permite să rulezi circuite mai profunde și să obții acuratețe mai mare.

Benchmark-uri​

QESEM a fost testat pe o gamă largă de cazuri de utilizare și aplicații. Următoarele exemple te pot ajuta să evaluezi ce tipuri de sarcini de lucru poți rula cu QESEM.

O figură de merit cheie pentru cuantificarea dificultății atât a atenuării erorilor, cât și a simulării clasice pentru un circuit și o observabilă dată este volumul activ: numărul de porți CNOT care afectează observabila în circuit. Volumul activ depinde de adâncimea și lățimea circuitului, de greutatea observabilei și de structura circuitului, care determină conul de lumină al observabilei. Pentru detalii suplimentare, consultați prezentarea de la IBM Quantum Summit 2024. QESEM oferă valoare deosebit de mare în regimul cu volum mare, furnizând rezultate fiabile pentru circuite și observabile generice.

Volum activ

AplicațieNumăr de qubițiDispozitivDescrierea circuituluiAcuratețeTimp totalUtilizare runtime
Circuit VQE8Eagle (r3)21 straturi totale, 9 baze de măsurare, lanț 1D98%35 min14 min
Kicked Ising28Eagle (r3)3 straturi unice x 3 pași, topologie 2D heavy-hex97%22 min4 min
Kicked Ising28Eagle (r3)3 straturi unice x 8 pași, topologie 2D heavy-hex97%116 min23 min
Simulare Hamiltoniană Trotterizată40Eagle (r3)2 straturi unice x 10 pași Trotter, lanț 1D97%3 ore25 min
Simulare Hamiltoniană Trotterizată119Eagle (r3)3 straturi unice x 9 pași Trotter, topologie 2D heavy-hex95%6,5 ore45 min
Kicked Ising136Heron (r2)3 straturi unice x 15 pași, topologie 2D heavy-hex99%52 min9 min

Acuratețea este măsurată aici relativ la valoarea ideală a observabilei: ⟨O⟩ideal−ϵ⟨O⟩ideal\frac{\langle O \rangle_{ideal} - \epsilon}{\langle O \rangle_{ideal}}, unde 'ϵ\epsilon' este precizia absolută a atenuării (stabilită de intrarea utilizatorului), iar ⟨O⟩ideal\langle O \rangle_{ideal} este observabila la circuitul fără zgomot. „Utilizarea runtime" măsoară utilizarea benchmark-ului în modul batch (suma utilizărilor job-urilor individuale), în timp ce „timpul total" măsoară utilizarea în modul sesiune (timpul real al experimentului), care include timpii clasici și de comunicație suplimentari. QESEM este disponibil pentru execuție în ambele moduri, astfel încât utilizatorii să poată face cel mai bun uz al resurselor disponibile.

Circuitele Kicked Ising de 28 qubiți simulează Cvazicristalul în Timp Discret studiat de Shinjo et al. (vezi arXiv 2403.16718 și Q2B24 Tokyo) pe trei bucle conectate ale ibm_kawasaki. Parametrii circuitului folosiți aici sunt (θx,θz)=(0.9π,0)(\theta_x, \theta_z) = (0.9 \pi, 0), cu o stare inițială feromagnetică ∣ψ0⟩=∣0⟩⊗n| \psi_0 \rangle = | 0 \rangle ^{\otimes n}. Observabila măsurată este valoarea absolută a magnetizării M=∣128∑i=027⟨Zi⟩∣M = |\frac{1}{28} \sum_{i=0}^{27} \langle Z_i \rangle|. Experimentul Kicked Ising la scară utilitară a fost rulat pe cei mai buni 136 qubiți ai ibm_fez; acest benchmark particular a fost rulat la unghiul Clifford (θx,θz)=(π,0)(\theta_x, \theta_z) = (\pi, 0), la care volumul activ crește lent cu adâncimea circuitului, ceea ce — împreună cu fidelitățile ridicate ale dispozitivului — permite acuratețe ridicată la un timp de execuție scurt.

Circuitele de simulare Hamiltoniană Trotterizată sunt pentru un model Ising cu câmp transversal la unghiuri fracționare: (θzz,θx)=(π/4,π/8)(\theta_{zz}, \theta_x) = (\pi / 4, \pi /8) și respectiv (θzz,θx)=(π/6,π/8)(\theta_{zz}, \theta_x) = (\pi / 6, \pi / 8) (vezi Q2B24 Tokyo). Circuitul la scară utilitară a fost rulat pe cei mai buni 119 qubiți ai ibm_brisbane, în timp ce experimentul de 40 qubiți a fost rulat pe cel mai bun lanț disponibil. Acuratețea este raportată pentru magnetizare; rezultate cu acuratețe ridicată au fost obținute și pentru observabile de greutate mai mare.

Circuitul VQE a fost dezvoltat împreună cu cercetători de la Centrul pentru Tehnologie și Aplicații Cuantice de la Deutsches Elektronen-Synchrotron (DESY). Observabila țintă a fost un Hamiltonian constând dintr-un număr mare de șiruri Pauli necomutante, subliniind performanța optimizată a QESEM pentru observabile multi-bază. Atenuarea a fost aplicată unui ansatz optimizat clasic; deși aceste rezultate sunt încă nepublicate, rezultate de aceeași calitate vor fi obținute pentru diferite circuite cu proprietăți structurale similare.

Primii pași​

Autentifică-te folosind cheia ta API IBM Quantum Platform și selectează Funcția Qiskit QESEM după cum urmează. (Acest fragment de cod presupune că ți-ai salvat deja contul în mediul local.)

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-catalog qiskit-ibm-runtime
import qiskit
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# verify that you have access to the function
catalog.list()
# load the function
qesem_function = catalog.load("qedma/qesem")

Exemple​

Exemplu de job de estimare a timpului​

Job-ul de estimare a timpului este util pentru estimarea timpului QPU necesar pentru un anumit pub și backend_name. backend_name poate fi setat și la orice backend simulator; de exemplu, fake_fez.

QESEM folosește o metodă de atenuare a erorilor cuasi-probabilistică, bazată pe caracterizare. Această metodă are un overhead de timp QPU care se scalează aproximativ ca:

TQPU=aeαIF⋅Vaϵ2+bT_{QPU} = a \frac{e^{\alpha IF\cdot V_a}}{\epsilon^2} + b

Unde VaV_a este volumul activ al circuitului, ϵ\epsilon este precizia țintă, iar IFIF este infidelitatea porților native.

Reține că "estimate_time_only": "empirical" folosește câteva minute de timp QPU pentru a estima timpul necesar pentru job (dacă backend-ul este un dispozitiv real; dacă este un simulator, atunci nu se folosește timp QPU). Acest lucru va dura de obicei în jur de 5 minute, dar nu mai mult de 10 minute. Dacă infidelitatea se schimbă drastic între job-ul empiric de estimare a timpului și job-ul de atenuare, timpul QPU se va schimba de asemenea drastic.

Pentru a începe, încearcă acest exemplu de bază pentru estimarea timpului QPU necesar pentru a rula QESEM pentru un pub dat:

# This cell is hidden from users
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend_name = service.least_busy().name
backend_name = "fake_fez"

circ = qiskit.QuantumCircuit(5)
circ.cx(0, 1)
circ.cx(2, 3)
circ.cx(1, 2)
circ.cx(3, 4)

avg_magnetization = qiskit.quantum_info.SparsePauliOp.from_sparse_list(
[("Z", [q], 1 / 5) for q in range(5)], num_qubits=5
)
other_observable = qiskit.quantum_info.SparsePauliOp.from_sparse_list(
[("ZZ", [0, 1], 1.0), ("XZ", [1, 4], 0.5)], num_qubits=5
)

time_estimation_job = qesem_function.run(
pubs=[(circ, [avg_magnetization, other_observable])],
options={
"estimate_time_only": "empirical",
},
backend_name=backend_name, # example: "fake_fez", "ibm_fez"
)
time_estimate_result = (
time_estimation_job.result()
) # a list of results per pub (circuit)

Următorul fragment de cod descrie cum să preiei diferite metrici de execuție din job-ul de estimare a timpului (estimate_time_only este setat):

pub_result = time_estimate_result[0]

print(
f"The estimated QPU time for mitigation for this PUB is: {pub_result.metadata['time_estimation_sec']}"
)
print(
f"The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}"
)
print(
f"Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}"
)
print(f"Total shots: {pub_result.metadata['total_shots']}")
print(f"Resource usage breakdown: {pub_result.metadata['resource_usage']}")
The estimated QPU time for mitigation for this PUB is: 300
The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): 0
Gates fidelity measured during the experiment: {'CZ': 0.9951354916722668, 'ID1Q': 0.9991246627329172}
Total shots: 220000
Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 33.6066133165732, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 184.53575124032795, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}

Când estimarea empirică a timpului este activată, QESEM rulează un număr mic de circuite pentru a oferi o estimare mai precisă a timpului QPU. Rezultatele de atenuare din aceste circuite sunt disponibile în câmpul empirical_estimation_mitigation_results al job-ului.

Deoarece aceste rezultate sunt derivate dintr-un eșantion limitat de circuite, ele sunt semnificativ mai puțin precise decât rezultatele finale obținute din job-ul complet de atenuare QESEM. Totuși, când circuitul este mic sau precizia țintă este scăzută, atenuarea efectuată în timpul estimării empirice a timpului poate fi suficientă pentru a atinge precizia dorită, iar job-ul complet de atenuare poate să nu fie necesar.

Câmpul empirical_estimation_mitigation_results este o listă de obiecte PrimitiveResult per parametru de intrare. Dacă circuitul nu este parametrizat, lista va avea lungimea 1.

empirical_estimation_mitigation_results = time_estimate_result[0].metadata[
"empirical_estimation_mitigation_results"
][0] # a list per parameter
print("Partial results for the observables:")

print(
f" Mitigated expectation values: {empirical_estimation_mitigation_results.data.evs}"
)
print(
f" Mitigated error bars: {empirical_estimation_mitigation_results.data.stds}"
)
print(
f" Number of shots used for mitigation: {empirical_estimation_mitigation_results.metadata['mitigation_shots']}"
)
transpiled_circ = empirical_estimation_mitigation_results.metadata[
"transpiled_circ"
]
print(f" Qubit mapping: {transpiled_circ['qubit_maps']}")
print(
f" Number of measurement bases: {transpiled_circ['num_measurement_bases']}\n"
)

# results per obs
emp_obs_results = empirical_estimation_mitigation_results.metadata["results"][
0
]
# print(f"Results for each observable: {results}")
print("Results for each observable:")

for i, (obs_array, result_dict) in enumerate(emp_obs_results):
# obs_array, result_dict = results
print(f"Observable {i+1}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} \u00b1 {result_dict['qesem']['error_bar']}"
)
Partial results for the observables:
Mitigated expectation values: [1.00347302 1.00693905]
Mitigated error bars: [0.00304061 0.00714276]
Number of shots used for mitigation: 180000
Qubit mapping: [[[0, 136], [1, 143], [2, 142], [3, 141], [4, 140]]]
Number of measurement bases: 2

Results for each observable:
Observable 1: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 1.003473015776871 ± 0.0030406128032204015
Observable 2: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.0069390542613554 ± 0.0071427606736885925

Exemplu de job de atenuare QESEM​

Următorul exemplu execută un job QESEM:

sample_job = qesem_function.run(
pubs=[(circ, [avg_magnetization, other_observable])],
backend_name=backend_name, # example: "ibm_fez"
# options = {
# "estimate_time_only": "empirical",
# "default_precision": 0.2, # Default precision is applied to all pubs that don't have a precision specified, see API reference for more details
# "max_execution_time": 3600, # You can specify a maximum QPU time in seconds, see API reference for more details
# "transpilation_level": "standard", # "minimal_with_layout_opt" for minimal transpilation, see API reference for more details
# "parallel_execution": True, # True for parallel execution, see API reference for more details
# },
)

Pentru o descriere detaliată a fiecărui câmp de intrare și opțiune, consultă referința API QESEM. Poți folosi API-urile familiare Qiskit Serverless pentru a verifica starea sarcinii de lucru a Funcției tale Qiskit sau pentru a returna rezultatele:

# Print the ID so you can use it later, if necessary
print(sample_job.job_id)
print(sample_job.status())
sample_result = sample_job.result()
3ac6b2df-15b0-4dc0-8f48-cf14bd20a1c8
DONE

Următorul fragment de cod demonstrează cum să recuperezi rezultatele atenuării și metricile de execuție. Acestea conțin date esențiale care permit o înțelegere mai profundă a modului în care diferiți parametri influențează execuția QESEM. Pot fi relevante și la redactarea unui articol bazat pe cercetarea ta.

for pub_idx, pub_result in enumerate(
sample_result
): # each element in the list is a result for a different pub, here we sent only one pub
print(f"\nPUB {pub_idx}:")
print(
f" The QPU time that this job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}"
)
print(
f" Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}"
)
print(f" Total shots: {pub_result.metadata['total_shots']}")
print(
f" Number of shots used for mitigation: {pub_result.metadata['mitigation_shots']}"
)
print(
f" Resource usage breakdown: {pub_result.metadata['resource_usage']}"
)
PUB 0:
The QPU time that this job took is (here it is 0 because we used fake_fez): 0.0
Gates fidelity measured during the experiment: {'CZ': 0.9953704216147041, 'ID1Q': 0.9991834123567518}
Total shots: 446000
Number of shots used for mitigation: 194000
Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 32.52745003718883, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 257.850521848537, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}

În metadata["results"], rezultatele sunt grupate mai întâi pe instanța de circuit și apoi pe observabilă.

print("Full QESEM mitigation results:")

for pub_idx, pub_result in enumerate(sample_result):
print(f"\nPUB {pub_idx}:")

print(f" Mitigated expectation values: {pub_result.data.evs}")
print(f" Mitigated error bars: {pub_result.data.stds}")
noisy_results = pub_result.metadata.get("noisy_results")
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")

print(" Transpiled circuits:")
for circ_idx, transpiled_circ in enumerate(
pub_result.metadata["transpiled_circs"]
):
print(f" Circuit {circ_idx}:")
# print(f" Circuit: \n {transpiled_circ['circuit']}") # not printing it because it's long but you can see the transpiled circuit itself
print(f" Qubit mapping: {transpiled_circ['qubit_maps']}")
print(
f" Measurement bases: {transpiled_circ['num_measurement_bases']}"
)

print(" Results for each observable:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}"
)
print(
f" Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}"
)
Full QESEM mitigation results:

PUB 0:
Mitigated expectation values: [1.00648343 1.00636289]
Mitigated error bars: [0.00253812 0.00693586]
Unmitigated expectation values: [0.98031429 0.96357143]
Unmitigated error bars: [0.00124128 0.00578812]
Transpiled circuits:
Circuit 0:
Qubit mapping: [[[0, 140], [1, 141], [2, 142], [3, 143], [4, 136]]]
Measurement bases: 2
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 1.0064834305181962 ± 0.002538119914534849
Unmitigated value: 0.9803142857142859 ± 0.0012412835813609938
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.0063628870614818 ± 0.006935859820870656
Unmitigated value: 0.9635714285714285 ± 0.005788121870526659

Detalierea principalelor rezultate:

  • mitigated: valoarea de așteptare complet atenuată QESEM.
  • unmitigated: rezultatul brut al zgomotului fizic fără atenuarea erorilor.

Rezultate de extrapolare euristică QESEM​

Într-o rulare standard QESEM cu un singur float precision, rezultatele includ, de asemenea, puncte de scalare a zgomotului disponibile automat, care sunt folosite pentru euristica QESEM. Aceste puncte sunt calculate fără resurse QPU suplimentare.

Scara 1.0 reprezintă nivelul de zgomot al dispozitivului fizic cu atenuarea citirii (REM), în timp ce scara 2.0 este punctul complementar amplificat de zgomot, tot cu REM. Aceste puncte sunt folosite pentru a produce rezultatul qesem_heuristic.

  • qesem_heuristic: o estimare de tip ZNE calculată din datele disponibile scalate în funcție de zgomot. În prezent, aceasta folosește extrapolarea exponențială.

  • noise_scaling.results_with_REM: valori de așteptare la diferite scări de zgomot, toate cu atenuarea citirii (REM).

Un detaliu subtil, dar important, este că rezultatul pentru scara 1.0 nu este același cu rezultatul unmitigated. Ambele corespund nivelului de zgomot al dispozitivului fizic, dar punctul pentru scara 1.0 include atenuarea citirii, în timp ce unmitigated nu.

print("QESEM heuristic results:")

for pub_idx, pub_result in enumerate(sample_result):
print(f"\nPUB {pub_idx}:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
qesem_heuristic = result_dict["qesem_heuristic"][0]
print(" QESEM heuristic:")
print(
f" Value: {qesem_heuristic['value']} ± {qesem_heuristic['error_bar']}"
)
print(
f" Extrapolation: {qesem_heuristic['extrapolation']}"
)
print(
f" Scale factors: {qesem_heuristic['scale_factors']}"
)
noise_scaling = result_dict["noise_scaling"]
print(" Noise scaling results:")
print(
f" Scaling method: {noise_scaling['scaling_method']}"
)
print(" Results with Readout mitigation (REM):")
for rem_result in sorted(
(
item
for item in noise_scaling["results_with_REM"]
if item["scale"] != 0.0
),
key=lambda item: item["scale"],
):
print(
f" Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}"
)
QESEM heuristic results:

PUB 0:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM heuristic:
Value: 1.0008161638888535 ± 0.0038859458884403964
Extrapolation: exponential
Scale factors: [1.0, 2.0]
Noise scaling results:
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 1.0: 0.9918395459270772 ± 0.0012565417579355634
Scale factor 2.0: 0.982943441922748 ± 0.0028919278067695018
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM heuristic:
Value: 0.9960853148925298 ± 0.013811635038961175
Extrapolation: exponential
Scale factors: [1.0, 2.0]
Noise scaling results:
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 1.0: 0.9902860583785115 ± 0.005921236914723409
Scale factor 2.0: 0.984520565414274 ± 0.006909522262347639
notă

Următoarele exemple se concentrează pe intrări și rezultate specifice funcționalității, deci nu afișează de fiecare dată metricile complete de execuție. Metadatele de nivel superior prezentate anterior, precum total_qpu_time, gate_fidelities, total_shots, mitigation_shots, și resource_usage, sunt disponibile și pentru aceste job-uri.

Unele variabile din exemplele anterioare, inclusiv backend-ul, observabilele și parametrii circuitului de bază, sunt reutilizate mai jos pentru concizie.

notă

Toate exemplele următoare pot fi rulate și cu estimarea empirică a timpului. Pentru a o activa, transmite "estimate_time_only": "empirical" în opțiunile funcției.

Exemplu de circuit parametrizat​

Mulți algoritmi evaluează același circuit la mai multe valori ale parametrilor. Trimiterea circuitului parametrizat ca un singur job QESEM permite QESEM să partajeze caracterizarea și calibrarea între instanțele circuitului, ceea ce poate reduce overhead-ul de timp QPU comparativ cu rularea unor job-uri separate.

Trimiterea unui circuit parametrizat necesită folosirea nivelului de transpilare "minimal_with_layout_opt". Circuitele trimise la acest nivel ar trebui să fie deja exprimate folosind porțile de bază ale backend-ului, în funcție de backend. La acest nivel, QESEM păstrează structura trimisă cât mai apropiată posibil de circuitul de intrare, respectă barierele în timpul layerificării (gruparea operațiilor în straturi de porți paralele cu doi qubiți) și tot gestionează automat maparea hardware la qubiți de fidelitate ridicată și conectivitatea dispozitivului.

În practică, aceasta înseamnă că ar trebui să transpilezi circuitele la porțile de bază ale backend-ului țintă înainte de trimitere. Un exemplu simplu de transpilare a porților de bază este prezentat mai jos.

QESEM suportă în prezent doar o observabilă per set de parametri. Cele două rânduri de parametri de mai jos sunt combinate (zip) cu cele două observabile: primul rând este măsurat cu avg_magnetization, iar al doilea rând este măsurat cu other_observable.

# Transpile to the backend basis gates only. With minimal_with_layout_opt, QESEM handles hardware mapping/connectivity and observable layout internally.
from qiskit_ibm_runtime.fake_provider import FakeFez

backend = FakeFez()
basis = backend.operation_names
print(basis)

param0 = qiskit.circuit.Parameter("param0")
param1 = qiskit.circuit.Parameter("param1")
parametrized_circ = qiskit.QuantumCircuit(5)
parametrized_circ.rx(param0, 0)
parametrized_circ.rx(param1, 1)
parametrized_circ.cx(0, 1)
parametrized_circ.cx(2, 3)
parametrized_circ.cx(1, 2)
parametrized_circ.cx(3, 4)

parametrized_circ = qiskit.transpile(
parametrized_circ, basis_gates=basis, optimization_level=1
)
parametrized_parameter_values = [[0.5, 0.1], [0.0, 0.6]]
parametrized_observables = [avg_magnetization, other_observable]

parametrized_job = qesem_function.run(
pubs=[
(
parametrized_circ,
parametrized_observables,
parametrized_parameter_values,
0.1,
)
],
backend_name=backend_name,
options={
"max_execution_time": 300,
"transpilation_level": "minimal_with_layout_opt",
},
)
print(parametrized_job.job_id)
print(parametrized_job.status())
d1b0e29b-196c-4896-aec6-44a268ebd874
DONE
parametrized_result = parametrized_job.result()
print("Parameterized circuit QESEM results:")

for pub_idx, pub_result in enumerate(parametrized_result):
print(f"\nPUB {pub_idx}:")
print(f" Mitigated expectation values: {pub_result.data.evs}")
print(f" Mitigated error bars: {pub_result.data.stds}")
noisy_results = pub_result.metadata["noisy_results"]
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Results for each parameter value:")
for param_idx, param_results in enumerate(pub_result.metadata["results"]):
print(
f" Parameter set {param_idx}: {parametrized_parameter_values[param_idx]}"
)
for obs_idx, (obs_array, result_dict) in enumerate(param_results):
print(f" Observable {obs_idx}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}"
)
print(
f" Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}"
)
Parameterized circuit QESEM results:

PUB 0:
Mitigated expectation values: [0.92392021 0.82517653]
Mitigated error bars: [0.00565281 0.00616016]
Unmitigated expectation values: [0.9028 0.78771429]
Unmitigated error bars: [0.00335142 0.00925413]
Results for each parameter value:
Parameter set 0: [0.5, 0.1]
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 0.923920210615709 ± 0.005652811570890183
Unmitigated value: 0.9028 ± 0.0033514176105045447
Parameter set 1: [0.0, 0.6]
Observable 0: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 0.8251765289285893 ± 0.006160161743353999
Unmitigated value: 0.7877142857142858 ± 0.009254130564027902

Exemplu multi-pub​

Execuția multi-pub este utilă atunci când vrei să rulezi mai multe circuite legate între ele într-un singur job QESEM. La fel ca execuția parametrizată, aceasta poate reduce overhead-ul deoarece QESEM poate partaja caracterizarea și calibrarea între instanțele de circuit în loc să le repete în job-uri separate.

Acest lucru este util în special pentru circuite cu o structură de straturi comună, cum ar fi sarcinile de lucru de tip Trotter, unde diferite circuite reutilizează aceleași straturi unice. În acest caz, rularea lor împreună poate reduce costul de caracterizare comparativ cu job-uri QESEM independente.

Job-urile multi-pub necesită "transpilation_level": "minimal_with_layout_opt". Ca și în exemplul parametrizat, circuitele ar trebui transpilate la porțile de bază ale backend-ului țintă înainte de trimitere. QESEM gestionează apoi intern conectivitatea dispozitivului, layout-ul și maparea la qubiți de fidelitate ridicată.

Fiecare PUB de mai jos conține un circuit și aceleași două observabile folosite mai devreme în notebook, astfel încât PrimitiveResult returnat conține un PubResult per circuit de intrare.

Exemplul de mai jos folosește două circuite Trotter simple cu același model de strat: circ_a are un strat Trotter, iar circ_b repetă același model de strat de două ori. Aceasta face structura comună explicită.

def make_trotter_circuit(num_qubits, num_layers, zz_angle=0.2, x_angle=0.1):
trotter_circ = qiskit.QuantumCircuit(num_qubits)
for _ in range(num_layers):
for q in range(num_qubits):
trotter_circ.rx(x_angle, q)
trotter_circ.barrier()
for q in range(0, num_qubits - 1, 2):
trotter_circ.rzz(zz_angle, q, q + 1)
trotter_circ.barrier()
for q in range(1, num_qubits - 1, 2):
trotter_circ.rzz(zz_angle, q, q + 1)
trotter_circ.barrier()
return trotter_circ

circ_a = make_trotter_circuit(num_qubits=5, num_layers=1)
circ_b = make_trotter_circuit(num_qubits=5, num_layers=2)
multi_pubs = [
(
qiskit.transpile(qci, basis_gates=basis, optimization_level=1),
[avg_magnetization, other_observable],
)
for qci in [circ_a, circ_b]
]

multi_circ_job = qesem_function.run(
pubs=multi_pubs,
backend_name=backend_name,
options={
"max_execution_time": 300,
"transpilation_level": "minimal_with_layout_opt",
"default_precision": 0.1,
},
)
print(multi_circ_job.job_id)
print(multi_circ_job.status())
e34565b8-7262-4133-a120-de42ce624a99
DONE
multi_circ_result = multi_circ_job.result()
print("Multi-pub QESEM results:")

for pub_idx, pub_result in enumerate(multi_circ_result):
print(f"\nPUB {pub_idx}:")
print(f" Mitigated expectation values: {pub_result.data.evs}")
print(f" Mitigated error bars: {pub_result.data.stds}")
noisy_results = pub_result.metadata["noisy_results"]
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Results for each observable:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}"
)
print(
f" Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}"
)
Multi-pub QESEM results:

PUB 0:
Mitigated expectation values: [0.99502406 1.02209332]
Mitigated error bars: [0.00483819 0.00707488]
Unmitigated expectation values: [0.96934286 0.97271429]
Unmitigated error bars: [0.00124855 0.00617294]
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 0.9950240647925642 ± 0.004838188086259301
Unmitigated value: 0.9693428571428573 ± 0.0012485470362492692
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.0220933230604674 ± 0.007074884384355636
Unmitigated value: 0.9727142857142859 ± 0.006172939375512439

PUB 1:
Mitigated expectation values: [0.98850017 1.02555188]
Mitigated error bars: [0.0077912 0.01672652]
Unmitigated expectation values: [0.93682857 0.95371429]
Unmitigated error bars: [0.00156245 0.00665735]
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 0.988500171577252 ± 0.007791203181151346
Unmitigated value: 0.9368285714285716 ± 0.001562451883089579
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.02555188098689 ± 0.016726524388086233
Unmitigated value: 0.9537142857142858 ± 0.006657345655544263

Exemplu de acordare cuasi-probabilistică a erorilor (QET)​

Acordarea cuasi-probabilistică a erorilor (QET) solicită valori de așteptare la factori de scalare a zgomotului selectați. Acest lucru este util pentru studii personalizate de scalare a zgomotului și fluxuri de lucru de extrapolare la zgomot zero (Zero-Noise Extrapolation). Scara 1.0 este nivelul de zgomot fizic, valorile între 0.0 și 1.0 reduc parțial zgomotul, iar valorile peste 1.0 amplifică zgomotul.

Pentru a folosi QET cu Qiskit Function, transmite un dicționar ca precizie a PUB. Dicționarul mapează fiecare factor de scalare a zgomotului solicitat la precizia sa țintă. Rezultatele returnate pentru factorii de scalare sunt stocate în noise_scaling.results_with_REM și includ atenuarea de citire (readout mitigation). Punctul de scalare 1.0 nu este așadar identic cu valoarea neatenuată, deoarece 1.0 include atenuarea de citire, în timp ce unmitigated nu o include.

Când este solicitat un factor de scalare, QESEM returnează de asemenea factorul de scalare complementar în jurul valorii 1.0, fără utilizare suplimentară a QPU. De exemplu, solicitarea 0.5 poate returna și 1.5, iar solicitarea 1.3 poate returna și 0.7. Precizia pe factorul de scalare complementar nu este garantată.

noise_scale_precision = {0.5: 0.15, 1.3: 0.2}

qet_job = qesem_function.run(
pubs=[
(
circ,
[avg_magnetization, other_observable],
None,
noise_scale_precision,
)
],
backend_name=backend_name,
options={"max_execution_time": 300},
)
print(qet_job.job_id)
print(qet_job.status())
8195fa58-f037-4651-8715-36ce1cdc5521
DONE
qet_result = qet_job.result()
print("QET noise-scaling results:")

for pub_idx, pub_result in enumerate(qet_result):
print(f"\nPUB {pub_idx}:")
noisy_results = pub_result.metadata["noisy_results"]
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Results for each observable:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
noise_scaling = result_dict["noise_scaling"]
print(
f" Scaling method: {noise_scaling['scaling_method']}"
)
print(" Results with Readout mitigation (REM):")
for rem_result in sorted(
(
item
for item in noise_scaling["results_with_REM"]
if item["scale"] != 0.0
),
key=lambda item: item["scale"],
):
print(
f" Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}"
)
QET noise-scaling results:

PUB 0:
Unmitigated expectation values: [0.97822857 0.96171429]
Unmitigated error bars: [0.00123812 0.00672958]
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 0.5: 0.9938730340199383 ± 0.0032116907357568275
Scale factor 0.7: 0.9963976191853445 ± 0.00036300258869586616
Scale factor 1.0: 0.9898115079506586 ± 0.0012525947426560995
Scale factor 1.3: 0.9864667065580341 ± 0.002633221613518526
Scale factor 1.5: 0.9838755527197551 ± 0.002948417797996015
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 0.5: 1.0006538544450332 ± 0.002121742014777343
Scale factor 0.7: 1.0004159801523036 ± 0.0021671375357823794
Scale factor 1.0: 0.9898058846339917 ± 0.00690183710903159
Scale factor 1.3: 0.9948946719997267 ± 0.002146532859610311
Scale factor 1.5: 0.9927220368192772 ± 0.0020875057190323882

Obținerea mesajelor de eroare​

Dacă starea workload-ului tău este ERROR, folosește job.result() pentru a obține mesajul de eroare, astfel:

# Get the result and truncate for readability
result = sample_job.result()
result_str = str(result)
max_length = 500 # Adjust this value as necessary

if len(result_str) > max_length:
truncated = (
result_str[:max_length]
+ f"... (truncated {len(result_str) - max_length} characters)"
)
else:
truncated = result_str

print(truncated)
PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(2,), dtype=float64>), stds=np.ndarray(<shape=(2,), dtype=float64>), shape=(2,)), metadata={'gate_fidelities': {'CZ': 0.9979444718552628, 'ID1Q': 0.9991994239814883}, 'total_shots': 498600, 'mitigation_shots': 223400, 'transpiled_circs': [{'circuit': 'OPENQASM 3.0;\ninclude "stdgates.inc";\nbit[76] c0;\nqubit[76] q0;\nrx(0) q0[54];\nrx(0) q0[59];\nrx(0) q0[75];\nrz(pi/2) q0[54];\nrz(pi/2) q0[59];\nrz(pi/2) q0[75];\nrx(pi/2) q0[54];\nr... (truncated 3771 characters)

Obținerea suportului​

Echipa de suport Qedma este aici să te ajute! Dacă întâmpini probleme sau ai întrebări despre utilizarea funcției QESEM Qiskit, nu ezita să ne contactezi. Personalul nostru de suport cu experiență și prietenos este pregătit să te asiste cu orice problemă tehnică sau întrebare ai.

Ne poți trimite un e-mail la support@qedma.com pentru asistență. Te rog să incluzi cât mai multe detalii posibil despre problema întâmpinată, pentru a ne ajuta să oferim un răspuns rapid și precis. Poți contacta, de asemenea, reprezentantul tău dedicat Qedma POC prin e-mail sau telefon.

Pentru a ne ajuta să te asistăm mai eficient, te rog să furnizezi următoarele informații când ne contactezi:

  • O descriere detaliată a problemei

  • ID-ul job-ului

  • Orice mesaje de eroare sau coduri relevante

Ne angajăm să îți oferim suport prompt și eficient pentru a te asigura că ai cea mai bună experiență posibilă cu Funcția noastră Qiskit.

Suntem mereu în căutarea de modalități de a îmbunătăți produsul nostru și îți primim sugestiile cu drag! Dacă ai idei despre cum putem îmbunătăți serviciile noastre sau funcționalități pe care ai dori să le vedem, te rog să ne trimiți gândurile tale la support@qedma.com.

Pașii următori​