Skip to main content
IBM Quantum Platform

Migrazione da Sampler e Estimator lato server a quelli lato client

Questa guida descrive come effettuare la migrazione dalle implementazioni lato server diIBM Quantum® e Sampler e Estimator alle loro nuove implementazioni lato client in qiskit-ibm-runtime . Le interfacce e le opzioni sono rimaste sostanzialmente invariate, quindi la maggior parte del codice funziona così com’è, ma ci sono alcune differenze di comportamento da tenere in considerazione.


Sfondo

Sampler ed Estimator sono interfacce primitive definite in Qiskit. Il servizio "IBM Quantum Compute " (precedentemente noto come "Qiskit Runtime ") ha storicamente fornito l'implementazione di queste primitive all'interno del proprio ambiente di esecuzione. Quando si chiama o sampler.run() estimator.run(), la richiesta viene inviata al servizio e tutte le operazioni di calcolo — comprese la soppressione e la mitigazione degli errori — avvengono sul lato server.

Questo approccio "black-box" è pratico: non devi preoccuparti dei dettagli di implementazione. Ma ciò rende anche difficile il debug, la personalizzazione o l'apprendimento delle primitive, poiché non è possibile vedere cosa succede durante l'elaborazione.

Il modello di esecuzione diretta, introdotto di recente, adotta un approccio opposto e offre un’esperienza “white-box ”. Tutte le intenzioni di progettazione vengono acquisite sul lato client, e un unico Executor primitivo sul lato server elabora tali input esattamente come indicato — senza prendere alcuna decisione implicita per conto dell'utente.

A partire dalla versione v0.50.0qiskit-ibm-runtime , Sampler ed Estimator sono stati reimplementati sul lato client sulla base di Executor. Offrono la stessa praticità e astrazione di prima, e ora è possibile esaminarne i dettagli di implementazione quando necessario . Poiché le interfacce e le opzioni rimangono sostanzialmente le stesse, la migrazione dovrebbe avvenire senza intoppi.

Nota: IBM Quantum supporta solo la versione 2 delle interfacce Sampler ed Estimator (BaseSamplerV2 e BaseEstimatorV2). Pertanto, in questa guida vengono semplicemente indicati come “Sampler” e “Estimator”.


Aggiornare le importazioni

Oggi è necessario importare esplicitamente le nuove implementazioni dai rispettivi moduli dedicati:

from qiskit_ibm_runtime.executor_sampler import Sampler
from qiskit_ibm_runtime.executor_estimator import Estimator

Nel prossimo futuro, le importazioni di primo livello verranno risolte nelle nuove implementazioni lato client e non sarà necessaria alcuna modifica al codice:

# Coming soon — the following code will import the new client-side implementations.
from qiskit_ibm_runtime import Sampler, Estimator

Allo stesso modo, se si creano oggetti di tipo “options”, è necessario importarli da qiskit_ibm_runtime.options_models “instead”, oppure passare semplicemente un semplice dizionario annidato:

from qiskit_ibm_runtime.options_models import SamplerOptions, EstimatorOptions

Cosa rimane uguale

  • Costruzione primitiva con a mode e options.
  • La firma run() e il formato “ PUB ”.
  • L'albero delle opzioni (options.twirling, options.resilience, options.default_shots, e così via).
  • La struttura dati dei risultati restituita da job.result().

Modifiche incompatibili nel nuovo Sampler

Modifica
Azione di migrazione
La primitiva sottostante è ora Executor. Sia l'interfaccia utente di IBM Quantum Platform che job.primitive_id mostreranno executor al posto di sampler.Aggiornare qualsiasi codice che faccia riferimento a job.primitive_id.
La nuova implementazione mappa gli input di Sampler agli input di Executor, quindi job.inputs restituisce gli input di Executor.Aggiornare qualsiasi codice che faccia riferimento a job.inputs. Vedi " Input di Job".
Ora una parte maggiore delle operazioni di pre-elaborazione e post-elaborazione viene eseguita sul lato client, quindi e sampler.run() job.result() potrebbero richiedere più tempo rispetto a prima.Abilita la registrazione INFO per monitorare lo stato di avanzamento dell'elaborazione lato client. Vedi " Abilita registrazione INFO ".
I metadati del circuito vengono copiati nei metadati dei risultati. I tipi di dati consentiti nei metadati dei risultati sono ora limitati a str, float, int, bool, e alle liste o ai dizionari di tali tipi.Se hai bisogno di altri tipi di dati, codificali prima come stringa (ad esempio, con base64 ).
Le classi delle opzioni (options_models.SamplerOptions e così via) sono ora modelli Pydantic anziché dataclass, quindi non possono più essere convertite in dizionari di tipo “ Python ” utilizzando asdict().Usa invece options.model_dump() questo.
Le classi di opzioni che in precedenza avevano il suffisso V2 (ExecutionOptionsV2 e così via) non lo hanno più, poiché le primitive di tipo V1 non sono più supportate.Rimuovere il suffisso V2 da queste classi di opzioni: sostituire ExecutionOptionsV2 con ExecutionOptions, ResilienceOptionsV2 con ResilienceOptionse SamplerExecutionOptionsV2 con SamplerExecutionOptions.
Se twirling è abilitato e shots (nei PUB o in run()), shots_per_randomization, e num_randomizations sono tutti specificati, allora num_randomizations * shots_per_randomization ha la precedenza su shots.Ometti e num_randomizations shots_per_randomization se desideri che venga utilizzato il valore shots .
Alcune operazioni di convalida degli input sono state spostate sul lato server e ora generano un'eccezione RuntimeError anziché IBMInputValueError.Aggiorna i tipi di eccezione che il tuo codice intercetta.
I valori di scatto misti in un unico lavoro non sono più supportati.Invia un lavoro separato per ciascun valore di esposizione. Per ulteriori approfondimenti, consultare la sezione " Ripartizione delle mansioni".

Modifiche incompatibili nel nuovo Estimator

Modifica
Azione di migrazione
La primitiva sottostante è ora Executor. Sia l'interfaccia utente di IBM Quantum Platform che job.primitive_id mostreranno executor al posto di estimator.Aggiornare qualsiasi codice che faccia riferimento a job.primitive_id.
La nuova implementazione mappa gli input dell'Estimator agli input dell'Executor, quindi job.inputs restituisce gli input dell'Executor.Aggiornare qualsiasi codice che faccia riferimento a job.inputs. Vedi " Input di Job".
Ora una parte maggiore delle operazioni di pre-elaborazione e post-elaborazione viene eseguita sul lato client, quindi e estimator.run() job.result() potrebbero richiedere più tempo rispetto a prima.Abilita la registrazione INFO per monitorare lo stato di avanzamento dell'elaborazione lato client. Vedi " Abilita registrazione INFO ".
I metadati del circuito vengono copiati nei metadati dei risultati. I tipi di dati consentiti nei metadati dei risultati sono ora limitati a str, float, int, bool, e alle liste o ai dizionari di tali tipi.Se hai bisogno di altri tipi di dati, codificali prima come stringa (ad esempio, con base64 ).
Le classi delle opzioni (options_models.EstimatorOptions e così via) sono ora modelli Pydantic anziché dataclass, quindi non possono più essere convertite in dizionari Python utilizzando asdict().Usa invece options.model_dump() questo.
Le classi di opzioni che avevano il suffisso V2 "before" (ExecutionOptionsV2 e così via) non lo hanno più, poiché le primitive V1 non sono più supportate.Rimuovere il suffisso V2 da queste classi di opzioni: sostituire ExecutionOptionsV2 con e ExecutionOptions ResilienceOptionsV2 con ResilienceOptions.
Tutte le opzioni di input vengono restituite nei metadati dei risultati, anziché un sottoinsieme selezionato.Nessuna — si tratta di informazioni a titolo puramente informativo.
Alcune operazioni di convalida degli input sono state spostate sul lato server e ora generano un'eccezione RuntimeError anziché IBMInputValueError.Aggiorna i tipi di eccezione che il tuo codice intercetta.
Niente più apprendimento implicito del rumore per PEA e PEC. L'apprendimento del rumore di misurazione per TREX è ancora supportato.Apprendere separatamente i modelli di rumore e trasmetterli a Estimator. Vedi “Esecuzione dell’apprendimento esplicito del rumore per PEA e PEC ”.
Il tipo di input di è ResilienceOptions.layer_noise_model diverso e può essere ricavato dai risultati NoiseLearnerV3 di.Vedi la sezione “Apprendimento esplicito del rumore per PEA e PEC” per sapere come apprendere i modelli di rumore utilizzando NoiseLearnerV3 e passarli a Estimator.
MeasureNoiseLearningOptions.shots_per_randomization non è più supportato.Per tutti i circuiti del processo viene utilizzato un unico valore di campionamento, compresi i circuiti di apprendimento del rumore di misurazione. Se è necessario utilizzare un valore di scatto diverso, applicare TREX con Estimator esterno qiskit-mitigation .
I valori con precisione mista all’interno di un singolo processo non sono più supportati.Invia un lavoro separato per ogni livello di precisione desiderato. Per ulteriori approfondimenti, consultare la sezione " Ripartizione delle mansioni".
L'opzione seed_estimator non è più supportata.Rimuovere qualsiasi options.seed_estimator assegnazione (impostarla genera un ValidationError). Non esiste un equivalente lato client, quindi i risultati non sono più riproducibili tramite questo seme.

Abilita la registrazione INFO

Poiché ora gran parte del lavoro viene svolto sul lato client, è utile poter seguire l'avanzamento di tale elaborazione. Abilita la registrazione a livello INFO per il qiskit_ibm_runtime logger:

import logging

logger = logging.getLogger("qiskit_ibm_runtime")
logger.setLevel(logging.INFO)

Eseguire l'apprendimento esplicito del rumore per PEA e PEC

Il nuovo Estimator non esegue più l'apprendimento implicito del rumore quando viene selezionato il metodo di mitigazione dell'errore PEA o PEC È necessario apprendere esplicitamente i modelli di rumore e fornirli come parametri. Utilizza la nuova funzione per NoiseLearnerV3 controllare la modalità di suddivisione dei circuiti in livelli. Accetta come input un elenco di istruzioni relative ai circuiti raggruppati (ad esempio, i livelli univoci).

Importante

PEA e PEC richiedono ora questo schema esplicito. Non saltare la fase di apprendimento del rumore, altrimenti il tuo codice non funzionerà. L'apprendimento del rumore di misurazione per TREX non subisce alcuna modifica e continua a funzionare come prima.

Allo stesso modo, se il tuo codice utilizza NoiseLearner e passa il modello di rumore risultante all'Estimator lato server, devi effettuare la migrazione a NoiseLearnerV3. NON utilizzare la versione precedente NoiseLearner, che è incompatibile con il nuovo Estimator.

Tutte le opzioni di apprendimento del rumore nella funzione Estimator (LayerNoiseLearningOptions) lato server corrispondono direttamente all'opzione NoiseLearnerV3 (NoiseLearnerV3Options), ad eccezione di max_layers_to_learn. Il numero di livelli da addestrare dipende invece dal numero di livelli passati a NoiseLearnerV3.

Ad esempio:

Stima lato server (con PEC abilitato):

from qiskit_ibm_runtime import Estimator

pubs = [...]  # Your PUBs
estimator = Estimator(mode, options)
estimator.options.resilience.pec_mitigation = True  # or zne_mitigation + pea amplifier
estimator.options.resilience.layer_noise_learning.num_randomizations = 64

job = estimator.run(pubs)

Stima lato client (con PEC abilitato):

from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3

pubs = [...]  # Your PUBs
estimator = Estimator(mode, options)
estimator.options.resilience.pec_mitigation = True  # or zne_mitigation + pea amplifier

# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)

# Learn the noise model for those layers (runs as a separate job).
learner = NoiseLearnerV3(mode)
learner.options.num_randomizations = 64  # Same as layer_noise_learning.num_randomizations
learner_job = learner.run(layers)
learner_result = learner_job.result()

# Convert results to Pauli-Lindblad noise maps.
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()

# Assign the learned noise maps so PEA/PEC uses them.
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)

# Now execute the target PUBs.
job = estimator.run(pubs)

Migrare da a NoiseLearner NoiseLearnerV3

NoiseLearner funziona solo con l'implementazione lato server di Estimator. Pertanto, se il tuo codice utilizza NoiseLearner per apprendere il modello di rumore e passarlo a Estimator, devi aggiornare il codice in modo che utilizzi NoiseLearnerV3.

Per ulteriori dettagli, consulta la guida Eseguire la migrazione da NoiseLearner a NoiseLearnerV3 .


Ripartizione delle mansioni

Quando è necessario suddividere un lavoro in più parti perché i valori di esposizione mista o di precisione in un unico lavoro non sono più supportati, tenere presente quanto segue:

  • Raggruppa i PUB in base al loro valore target: un’attività per ogni valore distinto, non un’attività per PUB... La suddivisione è un raggruppamento, quindi il numero totale di PUB inviati non cambia. Ad esempio, dato [[email protected], [email protected], [email protected]], inviare due lavori: [A, C] alle precision=0.01 e [B]alle precision=0.05. L'invio di e A C come lavori separati è meno efficiente, poiché ogni lavoro comporta un sovraccarico fisso.

  • Impara una volta sola e utilizza i modelli di rumore in tutti i lavori suddivisi. È più efficiente eseguire un unico NoiseLearnerV3 processo sull’unione di tutti i livelli. Il risultato di un’elaborazione eseguita da un “noise learner” contiene un elenco di oggetti NoiseLearnerV3Result , uno per ogni istruzione in ingresso, e segue lo stesso ordine dell’elenco in ingresso. È possibile utilizzare l'output di questo processo di apprendimento del rumore in tutti i processi di suddivisione (Estimator); i modelli di rumore relativi a livelli non presenti nei PUB di un processo di suddivisione vengono ignorati.

  • Invia prima Batch tutti i lavori suddivisi, poi raccogli i relativi risultati. La modalità di esecuzione Batch garantisce un'esecuzione parallela efficiente in presenza di più processi. Tuttavia, job.result() è un'operazione bloccante, quindi chiamarla all'interno del ciclo di invio serializza i lavori e annulla i vantaggi derivanti dall'uso di Batch. Assicurati di seguire lo schema “invia tutto e poi raccogli” (illustrato di seguito).

Nell'esempio seguente, e pub1 pub2 richiedono precision=0.5, mentre pub3 richiede precision=0.1:

group1_pubs = [pub1, pub2]
group2_pubs = [pub3]

with Batch(backend=backend) as batch:
    estimator = Estimator(mode=batch)
    estimator.options.resilience.pec_mitigation = True

    # Learn once, over the union of every job's layers.
    all_layers = estimator.find_unique_layers(group1_pubs + group2_pubs)
    learner_job = NoiseLearnerV3(mode=batch).run(all_layers)
    learner_result = learner_job.result()
    pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()

    # Assign the learned noise maps. Any layers not found in the input PUBs are ignored.
    estimator.options.resilience.layer_noise_model = zip(all_layers, pauli_lindblad_maps)

    # Submit every split job with different precision values.
    jobs = []
    jobs.append(estimator.run(group1_pubs, precision=0.5))
    jobs.append(estimator.run(group2_pubs, precision=0.1))

    # Block once, at the end — the jobs run in parallel.
    results = [job.result() for job in jobs]

Struttura degli input di lavoro

La nuova implementazione mappa gli input di Sampler o Estimator agli input di Executor, quindi job.inputs restituisce un dizionario contenente gli input di Executor. Questo dizionario contiene le seguenti voci:

Se in precedenza il tuo codice utilizzava job.inputs['options'] per individuare le opzioni specificate per il processo, ora puoi utilizzare job.result().metadata['options'] al suo posto.


Esegui il test in locale con un backend fittizio

Prima di passare alla fase di implementazione hardware, è possibile verificare il codice migrato rispetto a un Fake* backend per individuare tempestivamente eventuali errori di sintassi. Si prega di prendere nota dei seguenti dettagli relativi alla modalità di test locale:

  • Non riproduce i risultati ottenuti con l'hardware. La simulazione locale del rumore non riproduce perfettamente il rumore effettivo del dispositivo e, pertanto, i risultati potrebbero differire. L'esecuzione verifica che i percorsi delle opzioni e i tipi di valore siano corretti.
  • NoiseLearnerV3 non dispone di una modalità di test locale: mode accetta solo un vero Backend, Session, o Batch, quindi non è possibile eseguire la fase di apprendimento del rumore su un backend fittizio . Verifica quella parte del tuo codice confrontandola con quella NoiseLearnerV3 Riferimento API . Verificare che il costruttore, la forma di input run(instructions) e qualsiasi helper (come ad esempio l’helper “unique-layer”) siano utilizzati come descritto nella documentazione.

Ottimizzare il circuito per una simulazione locale efficiente

Un backend simulato utilizza un simulatore a vettore di stato (con rumore), il cui costo cresce in modo esponenziale con il numero di qubit e la profondità. Pertanto, un circuito di carico di lavoro realistico può bloccarsi o esaurire la memoria. Poiché i test locali devono solo verificare i percorsi delle opzioni (senza riprodurre risultati fisici), ridurre innanzitutto il circuito a uno di Clifford con ConvertISAToClifford, che arrotonda ogni RZ``RZZ//RX angolo al multiplo più vicino di π/2. I circuiti di Clifford vengono simulati in modo efficiente (simulazione con stabilizzatore) indipendentemente dalle loro dimensioni.

from qiskit.transpiler import PassManager
from qiskit_ibm_runtime.transpiler.passes import ConvertISAToClifford

clifford = PassManager([ConvertISAToClifford()]).run(isa_circuit)
# run `clifford` (not the original) through the fake-backend primitive

ConvertISAToClifford richiede un circuito ISA in ingresso (l'uscita di generate_preset_pass_manager(...).run(...) quello diretto al backend). È necessario tenere conto delle seguenti conseguenze durante la creazione dell’ PUB locale:

  • L'attributo .layout viene eliminato. Il circuito "cliffordizzato" mantiene lo stesso numero di qubit, ma clifford.layout è None , quindi non observable.apply_layout(clifford.layout) funziona. Disporre invece l'osservabile a partire dal circuito ISA pre-Clifford : isa_obs = observable.apply_layout(isa_circuit.layout), quindi eseguire (clifford, isa_obs).
  • I parametri sono associati altrove. Arrotondando gli angoli di rotazione, un circuito ISA parametrico si trasforma in un circuito di Clifford concreto, quindi diventa clifford.num_parameters 0. Un oggetto PUB che contiene ancora un array di valori dei parametri non supera la coercizione. Per l'esecuzione locale, eliminare l'array dei parametri dall' PUB; l'esecuzione hardware mantiene il circuito parametrico originale e i relativi valori.

Passi successivi

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