Skip to main content
IBM Quantum Platform

Eseguire circuiti dinamici

I circuiti dinamici sono potenti strumenti che consentono di misurare i qubit nel corso dell'esecuzione di un circuito quantistico e quindi di eseguire operazioni logiche classiche all'interno del circuito, sulla base dei risultati di tali misurazioni effettuate durante l'esecuzione. Questo processo è noto anche come feedforward classico. Sebbene siamo ancora agli inizi nel comprendere come sfruttare al meglio i circuiti dinamici, la comunità dei ricercatori quantistici ha già individuato una serie di casi d'uso, quali ad esempio:

Questi miglioramenti apportati dai circuiti dinamici, tuttavia, comportano alcuni compromessi. Le misurazioni a metà circuito e le operazioni classiche hanno in genere tempi di esecuzione più lunghi rispetto ai gate a due qubit, e questo aumento di tempo potrebbe vanificare i vantaggi derivanti dalla ridotta profondità del circuito. Pertanto, la riduzione della durata delle misurazioni a metà circuito rappresenta un’area di miglioramento prioritaria, in vista del lancio della nuova versione dei circuiti dinamici da parte di IBM Quantum®. Per ulteriori restrizioni relative all'uso dei circuiti dinamici, consultare la tabella di compatibilità delle funzionalità "Estimator" o "Sampler".

La specifica " OpenQASM e 3" definisce una serie di strutture di controllo del flusso, ma il servizio di calcolo " IBM Quantum " attualmente supporta solo l'istruzione if condizionale. In Qiskit SDK, ciò corrisponde al metodo if_test disponibile su QuantumCircuit. Questo metodo restituisce un gestore di contesto e viene solitamente utilizzato in un'istruzione with . Questa guida illustra come utilizzare questa istruzione condizionale.

Note

Gli esempi di codice riportati in questa guida utilizzano l'istruzione di misura standard per le misurazioni a circuito aperto. Tuttavia, si consiglia di utilizzare invece MidCircuitMeasure l'istruzione, se il backend la supporta. Per ulteriori dettagli, consultare la sezione "Misurazioni a metà circuito".

  • Il codice presente in questa pagina è stato sviluppato sulla base dei seguenti requisiti. Si consiglia di utilizzare queste versioni o quelle più recenti.

    qiskit[all]~=2.5.1
    qiskit-ibm-runtime~=0.47.0
    

Trova backend che supportano circuiti dinamici

Per individuare tutti i backend a cui il tuo account può accedere e che supportano i circuiti dinamici, esegui un codice simile al seguente. In questo esempio si presume che tu abbia salvato le tue credenziali di accesso. È inoltre possibile specificare esplicitamente le credenziali al momento dell'inizializzazione dell'account di IBM Quantum Compute Service. Questo ti consentirebbe, ad esempio, di visualizzare i backend disponibili su una specifica istanza o per un determinato tipo di piano.

Note
  • I backend disponibili per l'account dipendono dall'istanza specificata nelle credenziali.
  • La nuova versione dei circuiti dinamici è ora disponibile per tutti gli utenti su tutti i backend. Per ulteriori dettagli, consulta l'annuncio.
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
dc_backends = service.backends(dynamic_circuits=True)
print(dc_backends)

Output:

[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_boston')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_kingston')>]

Misure a metà circuito

Prima dell'introduzione di qiskit-ibm-runtime v0.43.0, measure questa era l'unica istruzione di misurazione disponibile in Qiskit. Le misurazioni a metà circuito, tuttavia, presentano requisiti di regolazione diversi rispetto alle misurazioni ai terminali (misurazioni effettuate all'estremità di un circuito). Ad esempio, quando si ottimizza una misurazione a metà circuito è necessario tenere conto della durata dell'istruzione, poiché le istruzioni più lunghe generano circuiti più rumorosi. Non è necessario tenere conto della durata delle istruzioni per le misurazioni terminali, poiché dopo tali misurazioni non seguono altre istruzioni.

Note

L'istruzione MidCircuitMeasure corrisponde measure_2 all'istruzione riportata nel file. del backend supported_instructions. Tuttavia, non measure_2 è supportato su tutti i backend. Usa service.backends(filters=lambda b: "measure_2" in b.supported_instructions) per trovare i backend che lo supportano. In futuro potrebbero essere aggiunte nuove misurazioni, ma ciò non è garantito.

MidCircuitMeasure metodo

In qiskit-ibm-runtime v0.43.0 è stata introdotta MidCircuitMeasure l'istruzione. Come suggerisce il nome, si tratta di una nuova istruzione di misurazione ottimizzata per l'esecuzione a metà ciclo sulle QPU dell' IBM®. Sebbene sia possibile utilizzare QuantumCircuit.measure per una misurazione a metà circuito, grazie alla sua struttura, MidCircuitMeasure rappresenta in genere la scelta migliore. Ad esempio, comporta un carico minore sul circuito rispetto all'uso di 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))

Output:

     ┌───┐┌────────────┐
q_0: ┤ X ├┤0           ├
     └───┘│            │
q_1: ─────┤  Measure_2 ├
          │            │
c_0: ═════╡0           ╞
          └────────────┘
c_1: ═══════════════════
                        
Note importanti
  • Per poter utilizzare le misurazioni, è necessario che sia presente almeno un registro classico.
  • La primitiva Sampler richiede misurazioni del circuito. È possibile aggiungere misure di circuito con la primitiva Estimator, ma queste vengono ignorate.

Store

A partire qiskit-ibm-runtime dalla versione 0.47.0, è possibile utilizzare l'istruzione store per salvare il risultato di un'espressione classica, qualora tale espressione debba essere utilizzata più volte. Le operazioni vengono parallelizzate automaticamente, rendendo il codice notevolmente più efficiente in fase di esecuzione.

Per ulteriori informazioni, consultare la guida sul feedforward classico e sul flusso di controllo.

Note

Quando si utilizza store per memorizzare un valore in un registro classico su un backend reale, tale valore viene salvato in memoria solo durante l'esecuzione e non viene copiato né restituito nel risultato del processo.

if_test Ad esempio, nel codice seguente, temp ha lo stesso valore di creg durante l'esecuzione, e funziona come previsto. Tuttavia, al termine del processo, il temp campo « BitArray » riportato nei risultati del processo non contiene il valore di creg. Cioè, job.result()[0].data.temp è 0.

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

Esempio completo

Il codice seguente crea ed esegue un circuito dinamico su un hardware dell 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()})"
)

Output:

>>>  Job ID:    d9mq9qnurbec73e67acg (DONE)

Limiti dell'informatica quantistica

Quando si eseguono circuiti dinamici in Quantum Compute, è necessario tenere presenti i seguenti vincoli.

  • A causa della memoria fisica limitata dell'elettronica di controllo, vi è anche un limite al numero di if istruzioni e alla dimensione dei loro operandi. Questo limite dipende dal numero di trasmissioni e dal numero di bit trasmessi in un processo (non in un circuito).

    Durante l'elaborazione di una if condizione, i dati di misura devono essere trasmessi alla logica di controllo per consentire tale valutazione. Una trasmissione è un trasferimento di dati classici univoci, mentre i bit trasmessi sono il numero di bit classici trasferiti. Considerare quanto segue:

    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)) ...

    Nell'esempio di codice precedente, i primi due if_test oggetti su c0 sono considerati un'unica trasmissione, poiché il contenuto di non c0 è cambiato e quindi non è necessario ritrasmetterlo. Quella if_test in onda c1 è una replica. Il primo trasmette tutti e tre i bit, c0 mentre il secondo ne trasmette solo uno, per un totale di quattro bit trasmessi.

    Attualmente, se si trasmettono 60 bit alla volta, il processo può comportare circa 300 trasmissioni. Se però si trasmette un solo bit alla volta, il processo può comportare 2400 trasmissioni.

  • L'operando utilizzato in if_test un'istruzione deve avere una lunghezza massima di 32 bit. Pertanto, se si sta confrontando un intero ClassicalRegister, la dimensione di quest'ultimo ClassicalRegister deve essere pari o inferiore a 32 bit. Se si confronta solo un singolo bit di un dato ClassicalRegister, tuttavia, questo ClassicalRegister può essere di qualsiasi dimensione (poiché l'operando è costituito da un solo bit).

    Ad esempio, il blocco di codice "Non valido" non funziona perché cr supera i 32 bit. È tuttavia possibile utilizzare un registro classico di larghezza superiore a 32 bit se si sta verificando un solo bit, come illustrato nel blocco di codice "Valid".

       cr = ClassicalRegister(50)
       qr = QuantumRegister(50)
       circuit = QuantumCircuit(qr, cr)
       ...
       circ.measure(qr, cr)
       with circ.if_test((cr, 15)):
          ...
  • Non sono consentite le condizioni annidate. Ad esempio, il seguente blocco di codice non funzionerà perché contiene un if_test all'interno di un altro if_test:

       c1 = ClassicalRegister(1, "c1")
       c2 = ClassicalRegister(2, "c2")
       ...
       with circ.if_test((c1, 1)):
        with circ.if_test(c2, 1)):
         ...
  • L'uso di reset o di misurazioni all'interno di espressioni condizionali non è supportato.

  • Le operazioni aritmetiche non sono supportate.

  • Consulta la tabella delle funzionalità di “ OpenQASM ” 3 per verificare quali funzionalità di “ OpenQASM ” 3 sono supportate da Qiskit e Quantum Compute.

  • Quando si utilizza OpenQASM 3 (anziché QuantumCircuit) come formato di input per passare i circuiti alle primitive IBM Quantum, sono supportate solo le istruzioni che possono essere caricate in Qiskit. Le operazioni classiche, ad esempio, non sono supportate perché non possono essere caricate in Qiskit. Per ulteriori informazioni, consultare la sezione “Importazione di un programma da OpenQASM 3 in Qiskit ”.

  • Le istruzioni for, while switch , e non sono supportate.


Utilizza i circuiti dinamici con Estimator

Poiché Estimator non supporta i circuiti dinamici, puoi utilizzare Sampler e creare invece i tuoi circuiti di misura.

Per riprodurre il comportamento di Estimator, procedere come segue:

  1. Raggruppare i termini di tutte le variabili osservabili in una partizione. Ciò può essere fatto utilizzando, ad esempio, PauliList APIil.
    Note

    È possibile utilizzare l'attributo BitArray primitive per calcolare i valori attesi delle grandezze osservabili fornite.

  2. Eseguire un ciclo di modifica della base per ogni partizione (a seconda della modifica della base necessaria per ciascuna partizione). Per ulteriori informazioni, consultare il modulo measurement_bases aggiuntivo "Basi di misurazione". Per ulteriori informazioni, consultare la documentazione relativa al pacchetto di utilità dell'add-on Qiskit.
  3. Somma i risultati relativi a ciascuna partizione.

Limitazioni

Consultare una tabella di compatibilità delle funzionalità per comprendere le limitazioni relative all'uso dei circuiti dinamici. Si noti che la compatibilità delle funzionalità non dipende dalle primitive.


Passi successivi

Suggerimenti
Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.