Přeskočit na hlavní obsah

Spouštění dynamických obvodů

Verze balíčků

Kód na této stránce byl vyvinut s použitím následujících požadavků. Doporučujeme používat tyto nebo novější verze.

qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1

Dynamické obvody jsou mocnými nástroji, pomocí nichž můžeš měřit qubit uprostřed spouštění kvantového obvodu a poté provádět operace klasické logiky v rámci obvodu, a to na základě výsledku těchto mid-circuit měření. Tento proces se také nazývá klasická zpětná vazba. Ačkoli jsou to teprve počátky pochopení toho, jak nejlépe využít dynamické obvody, kvantová výzkumná komunita již identifikovala řadu případů použití, jako jsou například:

Tato zlepšení přinesená dynamickými obvody však přinášejí kompromisy. Mid-circuit měření a klasické operace mají obvykle delší dobu spouštění než dvouQubitové Gate, a tento nárůst času může negovat výhody snížené hloubky obvodu. Proto je zkrácení délky mid-circuit měření oblastí zaměření zlepšení, jak IBM Quantum® vydává novou verzi dynamických obvodů. Další omezení při používání dynamických obvodů najdeš v tabulce kompatibility funkcí Estimator nebo Sampler.

Specifikace OpenQASM 3 definuje řadu řídicích struktur, ale Qiskit Runtime v současnosti podporuje pouze podmíněný příkaz if. V Qiskit SDK to odpovídá metodě if_test na QuantumCircuit. Tato metoda vrací správce kontextu a je obvykle používána v příkazu with. Tento průvodce popisuje, jak tento podmíněný příkaz používat.

poznámka

Příklady kódu v tomto průvodci používají standardní instrukci measure pro mid-circuit měření. Doporučuje se však místo toho použít instrukci MidCircuitMeasure, pokud ji Backend podporuje. Podrobnosti najdeš v sekci Mid-circuit measurements.

Hledání Backendů podporujících dynamické obvody

Chceš-li najít všechny Backendy, ke kterým má tvůj účet přístup a podporují dynamické obvody, spusť kód jako následující. Tento příklad předpokládá, že máš uloženy přihlašovací údaje. Přihlašovací údaje můžeš také explicitně zadat při inicializaci svého účtu Qiskit Runtime Service. To by ti umožnilo zobrazit Backendy dostupné na konkrétní instanci nebo typu plánu, například.

Poznámky
  • Backendy dostupné pro účet závisí na instanci zadané v přihlašovacích údajích.
  • Nová verze dynamických obvodů je nyní dostupná všem uživatelům na všech Backendech. Více podrobností najdeš v oznámení.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# This cell is hidden from users. It hides all those "...instance was not set..." warnings.
import warnings

warnings.filterwarnings("ignore", message=".*Instance was not set*")
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
dc_backends = service.backends(dynamic_circuits=True)
print(dc_backends)
[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_kingston')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_boston')>]

Mid-circuit měření

Před verzí qiskit-ibm-runtime v0.43.0 byla measure jedinou instrukcí měření v Qiskit. Mid-circuit měření mají však jiné požadavky na ladění než terminální měření (měření, která se dějí na konci obvodu). Například při ladění mid-circuit měření musíš zohledňovat dobu trvání instrukce, protože delší instrukce způsobují hlučnější obvody. U terminálních měření nemusíš zohledňovat dobu trvání instrukce, protože po terminálních měřeních nenásledují žádné instrukce.

poznámka

Instrukce MidCircuitMeasure se mapuje na instrukci measure_2 hlášenou v supported_instructions Backendu. Avšak measure_2 není podporována na všech Backendech. Použij service.backends(filters=lambda b: "measure_2" in b.supported_instructions) k nalezení Backendů, které ji podporují. V budoucnu mohou být přidána nová měření, ale není to zaručeno.

Metoda MidCircuitMeasure

Ve verzi qiskit-ibm-runtime v0.43.0 byla zavedena instrukce MidCircuitMeasure. Jak název napovídá, jde o novou instrukci měření, která je optimalizována pro mid-circuit na IBM® QPU. Ačkoli pro mid-circuit měření můžeš použít QuantumCircuit.measure, kvůli svému designu je MidCircuitMeasure obvykle lepší volbou. Například přidává do tvého obvodu méně režie než při použití QuantumCircuit.measure.

from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime.circuit import MidCircuitMeasure

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, dynamic_circuits=True
)

circ = QuantumCircuit(2, 2)
circ.x(0)
circ.append(MidCircuitMeasure(), [0], [0])
# circ.measure([0], [0])
# circ.measure_all()
print(circ.draw(cregbundle=False))
┌───┐┌────────────┐
q_0: ┤ X ├┤0 ├
└───┘│ │
q_1: ─────┤ Measure_2 ├
│ │
c_0: ═════╡0 ╞
└────────────┘
c_1: ═══════════════════
Důležité poznámky
  • Aby bylo možné použít měření, musí existovat alespoň jeden klasický registr.
  • Primitiv Sampler vyžaduje měření obvodů. S primitivem Estimator můžeš přidat měření obvodů, ale jsou ignorována.

Store

S verzí qiskit-ibm-runtime 0.47.0 nebo novější můžeš použít instrukci store k uložení výsledku klasického výrazu, pokud bude tento výraz opakovaně používán. Operace jsou automaticky paralelizovány, což výrazně zvyšuje efektivitu tvého kódu za běhu.

Více informací najdeš v průvodci Klasická zpětná vazba a řízení toku.

poznámka

Když použiješ store k uložení hodnoty do klasického registru na reálném Backendu, tato hodnota je uložena pouze v paměti během spouštění a není kopírována ani vrácena ve výsledku úlohy.

Například v následujícím kódu má temp stejnou hodnotu jako creg během spouštění a if_test funguje podle očekávání. Po dokončení úlohy však temp BitArray vrácený ve výsledku úlohy neobsahuje hodnotu creg. To znamená, že job.result()[0].data.temp je 0.

creg = ClassicalRegister(3, "c")
temp = ClassicalRegister(3, "temp")
...
qc.store(temp, creg)
with circuit.if_test((temp, 0b001)):
...

Kompletní příklad

Následující kód vytváří a spouští dynamický obvod na hardwaru IBM®.

from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.transpiler import generate_preset_pass_manager

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, dynamic_circuits=True
)

# Create a dynamic circuit

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
qc = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

qc.h(q0)
qc.measure(q0, c0)
with qc.if_test((c0, 1)):
qc.x(q0)
qc.measure(q0, c0)

# Convert to an ISA circuit for the given backend

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

# Generate samplers for backend targets
sampler = SamplerV2(backend)

# Submit jobs
sampler_job = sampler.run([isa_circuit])
result = sampler_job.result()

print(
f">>> {' Job ID:':<10} {sampler_job.job_id()} ({sampler_job.status()})"
)
>>> Job ID: d88cakp789is7391vq0g (DONE)

Omezení Qiskit Runtime

Při spouštění dynamických obvodů v Qiskit Runtime měj na paměti následující omezení.

  • Kvůli omezené fyzické paměti v řídicí elektronice existuje také limit počtu příkazů if a velikosti jejich operandů. Tento limit je funkcí počtu broadcastů a počtu broadcastovaných bitů v úloze (nikoli v obvodu).

    Při zpracování podmínky if musí být data měření přenesena do řídicí logiky, aby bylo možné provést toto vyhodnocení. Broadcast je přenos jedinečných klasických dat a broadcastované bity jsou počet přenášených klasických bitů. Uvažuj následující:

    c0 = ClassicalRegister(3)
    c1 = ClassicalRegister(5)
    ...
    with circuit.if_test((c0, 1)) ...
    with circuit.if_test((c0, 3)) ...
    with circuit.if_test((c1[2], 1)) ...

    V předchozím příkladu kódu jsou první dva objekty if_test na c0 považovány za jeden broadcast, protože obsah c0 se nezměnil, a tedy není třeba jej znovu broadcastovat. if_test na c1 je druhý broadcast. První broadcastuje všechny tři bity v c0 a druhý broadcastuje pouze jeden bit, celkem čtyři broadcastované bity.

    V současnosti platí, že pokud broadcastuješ 60 bitů pokaždé, úloha může mít přibližně 300 broadcastů. Pokud však broadcastuješ pouze jeden bit pokaždé, úloha může mít 2400 broadcastů.

  • Operand použitý v příkazu if_test musí být 32 nebo méně bitů. Pokud tedy porovnáváš celý ClassicalRegister, velikost tohoto ClassicalRegister musí být 32 nebo méně bitů. Pokud však porovnáváš pouze jeden bit z ClassicalRegister, může mít tento ClassicalRegister libovolnou velikost (protože operand je pouze jeden bit).

    Například blok kódu „Neplatné" nefunguje, protože cr má více než 32 bitů. Klasický registr širší než 32 bitů však můžeš použít, pokud testuješ pouze jeden bit, jak je uvedeno v bloku kódu „Platné".

    cr = ClassicalRegister(50)
    qr = QuantumRegister(50)
    circuit = QuantumCircuit(qr, cr)
    ...
    circ.measure(qr, cr)
    with circ.if_test((cr, 15)):
    ...
  • Vnořené podmíněné příkazy nejsou povoleny. Například následující blok kódu nebude fungovat, protože obsahuje if_test uvnitř jiného if_test:

    c1 = ClassicalRegister(1, "c1")
    c2 = ClassicalRegister(2, "c2")
    ...
    with circ.if_test((c1, 1)):
    with circ.if_test(c2, 1)):
    ...
  • Použití reset nebo měření uvnitř podmíněných příkazů není podporováno.

  • Aritmetické operace nejsou podporovány.

  • V tabulce funkcí OpenQASM 3 zjistíš, které funkce OpenQASM 3 jsou podporovány v Qiskit a Qiskit Runtime.

  • Pokud je jako vstupní formát pro předávání obvodů do primitivů Qiskit Runtime použit OpenQASM 3 (místo QuantumCircuit), jsou podporovány pouze instrukce, které lze načíst do Qiskit. Klasické operace například nejsou podporovány, protože je nelze načíst do Qiskit. Více informací najdeš v části Import programu OpenQASM 3 do Qiskit.

  • Instrukce for, while a switch nejsou podporovány.

Použití dynamických obvodů s Estimator

Protože Estimator nepodporuje dynamické obvody, můžeš místo toho použít Sampler a sestavit své vlastní obvody měření.

Chceš-li replikovat chování Estimator, postupuj následovně:

  1. Seskup termíny všech observables do oddílu. To lze provést například pomocí API PauliList.
    poznámka

    Atribut primitivu BitArray můžeš použít k výpočtu očekávaných hodnot poskytnutých observables.

  2. Pro každý oddíl spusť jeden obvod změny základu (jakoukoli změnu základu, která musí být pro každý oddíl provedena). Více informací najdeš v modulu measurement_bases addonového nástroje Measurement bases. Více informací najdeš v dokumentaci balíčku Qiskit addon utilities.
  3. Přidej zpět dohromady výsledky pro každý oddíl.

Omezení

Projdi si jakoukoli Tabulku kompatibility funkcí, abys pochopil omezení při používání dynamických obvodů. Upozorňujeme, že kompatibilita funkcí nezávisí na primitivu.

Další kroky

Doporučení