Wykonywanie obwodów dynamicznych
Wersje pakietów
Kod na tej stronie został opracowany przy użyciu następujących wymagań. Zalecamy używanie tych lub nowszych wersji.
qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
Obwody dynamiczne to potężne narzędzia, za pomocą których możesz mierzyć kubity w środku wykonywania obwodu kwantowego, a następnie wykonywać klasyczne operacje logiczne wewnątrz obwodu, oparte na wynikach tych pomiarów śródkombinacyjnych. Proces ten jest również znany jako klasyczne sprzężenie zwrotne. Choć to są wczesne dni rozumienia, jak najlepiej korzystać z obwodów dynamicznych, społeczność badań kwantowych już zidentyfikowała wiele przypadków użycia, takich jak:
- Efektywne przygotowywanie stanów kwantowych, takie jak stan GHZ, stan W (więcej informacji o stanie W znajdziesz w "State preparation by shallow circuits using feed forward") oraz szeroką klasę stanów iloczynu macierzowego
- Efektywne splątanie długozasięgowe między kubitami na tym samym układzie przy użyciu płytkich obwodów
- Efektywne próbkowanie obwodów podobnych do IQP
Ulepszenia wprowadzane przez obwody dynamiczne wiążą się jednak z kompromisami. Pomiary śródkombinacyjne i operacje klasyczne mają zazwyczaj dłuższy czas wykonania niż bramki dwuqubitowe, a ten wzrost czasu może niwelować korzyści ze zmniejszonej głębokości obwodu. Dlatego skracanie długości pomiaru śródkombinacyjnego jest priorytetowym obszarem ulepszeń, gdy IBM Quantum® wydaje nową wersję obwodów dynamicznych. W przypadku innych ograniczeń przy używaniu obwodów dynamicznych, sprawdź tabelę kompatybilności funkcji Estimator lub Sampler.
Specyfikacja OpenQASM 3 definiuje wiele struktur przepływu sterowania, ale Qiskit Runtime obecnie obsługuje tylko warunkową instrukcję if. W Qiskit SDK odpowiada to metodzie if_test na QuantumCircuit. Ta metoda zwraca menedżer kontekstu i jest zazwyczaj używana w instrukcji with. Ten przewodnik opisuje, jak używać tej instrukcji warunkowej.
Przykłady kodu w tym przewodniku używają standardowej instrukcji miary do pomiarów śródkombinacyjnych. Zalecamy jednak używanie instrukcji MidCircuitMeasure, jeśli backend ją obsługuje. Szczegóły znajdziesz w sekcji Pomiary śródkombinacyjne.
Znajdź backendy obsługujące obwody dynamiczne
Aby znaleźć wszystkie backendy dostępne dla Twojego konta i obsługujące obwody dynamiczne, uruchom kod podobny do poniższego. Ten przykład zakłada, że zapisałeś dane logowania. Możesz również jawnie podać dane uwierzytelniające podczas inicjalizacji konta usługi Qiskit Runtime. Pozwoli Ci to na przykład przeglądać backendy dostępne w konkretnej instancji lub typie planu.
- Backendy dostępne dla konta zależą od instancji podanej w danych uwierzytelniających.
- Nowa wersja obwodów dynamicznych jest teraz dostępna dla wszystkich użytkowników na wszystkich backendach. Szczegóły znajdziesz w ogłoszeniu.
# 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')>]
Pomiary śródkombinacyjne
Przed qiskit-ibm-runtime v0.43.0, measure była jedyną instrukcją pomiaru w Qiskit. Pomiary śródkombinacyjne mają jednak inne wymagania strojenia niż pomiary końcowe (pomiary, które następują na końcu obwodu). Na przykład przy strojeniu pomiaru śródkombinacyjnego należy uwzględnić czas trwania instrukcji, ponieważ dłuższe instrukcje powodują bardziej zaszumione obwody. Dla pomiarów końcowych nie trzeba brać pod uwagę czasu trwania instrukcji, ponieważ po pomiarach końcowych nie ma żadnych instrukcji.
Instrukcja MidCircuitMeasure mapuje się na instrukcję measure_2 raportowaną w supported_instructions backendu. Jednak measure_2 nie jest obsługiwane na wszystkich backendach. Użyj service.backends(filters=lambda b: "measure_2" in b.supported_instructions), aby znaleźć backendy, które go obsługują. W przyszłości mogą zostać dodane nowe pomiary, ale nie jest to gwarantowane.
Metoda MidCircuitMeasure
W qiskit-ibm-runtime v0.43.0 wprowadzono instrukcję MidCircuitMeasure. Jak sama nazwa wskazuje, jest to nowa instrukcja pomiaru zoptymalizowana pod kątem pomiarów śródkombinacyjnych na QPU IBM®. Choć możesz używać QuantumCircuit.measure do pomiaru śródkombinacyjnego, ze względu na projekt MidCircuitMeasure jest zazwyczaj lepszym wyborem. Na przykład dodaje mniejszy narzut do obwodu niż przy użyciu 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: ═══════════════════
- Musi istnieć co najmniej jeden rejestr klasyczny, aby używać pomiarów.
- Prymityw Sampler wymaga pomiarów obwodu. Możesz dodawać pomiary obwodu z prymitywem Estimator, ale są one ignorowane.
Store
W wersji qiskit-ibm-runtime 0.47.0 lub nowszej możesz używać instrukcji store, aby zapisać wynik wyrażenia klasycznego, jeśli to wyrażenie będzie wielokrotnie używane. Operacje są automatycznie zrównoleglane, co sprawia, że kod jest znacznie bardziej wydajny w czasie wykonania.
Więcej informacji znajdziesz w przewodniku Klasyczne sprzężenie zwrotne i przepływ sterowania.
Gdy używasz store do zapisania wartości do rejestru klasycznego na prawdziwym backendzie, wartość ta jest przechowywana tylko w pamięci podczas wykonania i nie jest kopiowana ani zwracana w wyniku zadania.
Na przykład w poniższym kodzie temp ma tę samą wartość co creg podczas wykonania, a if_test działa zgodnie z oczekiwaniami. Jednak po zakończeniu zadania BitArray wartości temp zwrócony w wyniku zadania nie zawiera wartości creg. Tzn. job.result()[0].data.temp wynosi 0.
creg = ClassicalRegister(3, "c")
temp = ClassicalRegister(3, "temp")
...
qc.store(temp, creg)
with circuit.if_test((temp, 0b001)):
...
Pełny przykład
Poniższy kod tworzy i uruchamia obwód dynamiczny na sprzęcie 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)
Ograniczenia Qiskit Runtime
Należy pamiętać o następujących ograniczeniach podczas uruchamiania obwodów dynamicznych w Qiskit Runtime.
-
Ze względu na ograniczoną pamięć fizyczną na elektronice sterującej istnieje również limit liczby instrukcji
ifi rozmiaru ich operandów. Ten limit jest funkcją liczby rozgłoszeń i liczby rozgłoszonych bitów w zadaniu (nie w obwodzie).Podczas przetwarzania warunku
ifdane pomiarów muszą być transferowane do logiki sterowania w celu dokonania tej oceny. Rozgłoszenie to transfer unikalnych danych klasycznych, a rozgłoszone bity to liczba transferowanych bitów klasycznych. Rozważ następujące: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)) ...W poprzednim przykładzie kodu pierwsze dwa obiekty
if_testnac0są uważane za jedno rozgłoszenie, ponieważ zawartośćc0nie zmieniła się, a zatem nie musi być ponownie rozgłaszana.if_testnac1to drugie rozgłoszenie. Pierwsze rozgłasza wszystkie trzy bity wc0, a drugie tylko jeden bit, co daje łącznie cztery rozgłoszone bity.Obecnie, jeśli rozgłaszasz 60 bitów za każdym razem, zadanie może mieć około 300 rozgłoszeń. Jeśli jednak rozgłaszasz tylko jeden bit za każdym razem, zadanie może mieć 2400 rozgłoszeń.
-
Operand używany w instrukcji
if_testmusi mieć co najwyżej 32 bity. Dlatego jeśli porównujesz całyClassicalRegister, rozmiar tegoClassicalRegistermusi wynosić co najwyżej 32 bity. Jeśli jednak porównujesz tylko jeden bit zClassicalRegister, tenClassicalRegistermoże mieć dowolny rozmiar (ponieważ operandem jest tylko jeden bit).Na przykład blok kodu "Niepoprawny" nie działa, ponieważ
crma więcej niż 32 bity. Możesz jednak używać rejestru klasycznego szerszego niż 32 bity, jeśli testujesz tylko jeden bit, jak pokazano w bloku kodu "Poprawny".- Niepoprawny
- Poprawny
cr = ClassicalRegister(50)qr = QuantumRegister(50)circuit = QuantumCircuit(qr, cr)...circ.measure(qr, cr)with circ.if_test((cr, 15)):...cr = ClassicalRegister(50)qr = QuantumRegister(50)circuit = QuantumCircuit(qr, cr)...circ.measure(qr, cr)with circ.if_test((cr[5], 1)):... -
Zagnieżdżone warunki nie są dozwolone. Na przykład poniższy blok kodu nie zadziała, ponieważ ma
if_testwewnątrz innegoif_test:- Niepoprawny
- Poprawny
c1 = ClassicalRegister(1, "c1")c2 = ClassicalRegister(2, "c2")...with circ.if_test((c1, 1)):with circ.if_test(c2, 1)):...cr = ClassicalRegister(2)...with circuit.if_test((cr, 0b11)):... -
resetlub pomiary wewnątrz warunków nie są obsługiwane. -
Operacje arytmetyczne nie są obsługiwane.
-
Zobacz tabelę funkcji OpenQASM 3, aby określić, które funkcje OpenQASM 3 są obsługiwane przez Qiskit i Qiskit Runtime.
-
Gdy OpenQASM 3 (zamiast
QuantumCircuit) jest używany jako format wejściowy do przekazywania obwodów do prymitywów Qiskit Runtime, obsługiwane są tylko instrukcje, które można załadować do Qiskit. Na przykład operacje klasyczne nie są obsługiwane, ponieważ nie można ich załadować do Qiskit. Więcej informacji znajdziesz w Import programu OpenQASM 3 do Qiskit. -
Instrukcje
for,whileiswitchnie są obsługiwane.
Używanie obwodów dynamicznych z Estimator
Ponieważ Estimator nie obsługuje obwodów dynamicznych, możesz używać Sampler i budować własne obwody pomiarowe.
Aby odtworzyć zachowanie Estimator, wykonaj następujący proces:
- Podziel terminy wszystkich obserwabli na partycję. Można to zrobić na przykład za pomocą API
PauliList.uwagaMożesz użyć atrybutu prymitywu
BitArraydo obliczania wartości oczekiwanych podanych obserwabli. - Wykonaj jeden obwód zmiany bazy dla każdej partycji (niezależnie od tego, jaką zmianę bazy trzeba wykonać dla każdej partycji). Więcej informacji znajdziesz w module
measurement_basespakietu Measurement bases addon utility. Więcej informacji znajdziesz w dokumentacji pakietu Qiskit addon utilities. - Dodaj z powrotem wyniki dla każdej partycji.
Ograniczenia
Przejrzyj dowolną tabelę kompatybilności funkcji, aby zrozumieć ograniczenia podczas używania obwodów dynamicznych. Pamiętaj, że kompatybilność funkcji nie zależy od prymitywu.
Następne kroki
- Dowiedz się, jak implementować dokładne dynamiczne odsprzęganie za pomocą stretch.
- Przejrzyj przewodnik klasyczne sprzężenie zwrotne i przepływ sterowania.
- Użyj wizualizacji harmonogramu obwodu do debugowania i optymalizacji obwodów dynamicznych.
- Nie wszystkie funkcje są kompatybilne z obwodami dynamicznymi. Sprawdź sekcję kompatybilności funkcji dla Sampler lub Executor, aby uzyskać szczegóły.