Vai al contenuto principale

Specificare le opzioni

Versioni dei pacchetti

Il codice in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Si consiglia di usare queste versioni o versioni più recenti.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1

Puoi usare le opzioni per personalizzare le primitive Estimator e Sampler. Questa sezione si concentra su come specificare le opzioni delle primitive Qiskit Runtime. Anche se l'interfaccia del metodo run() delle primitive è comune a tutte le implementazioni, le relative opzioni non lo sono. Consulta i riferimenti API corrispondenti per informazioni sulle opzioni di qiskit.primitives e qiskit_aer.primitives.

Note sulla specifica delle opzioni nelle primitive:

  • SamplerV2 e EstimatorV2 hanno classi di opzioni separate. Puoi visualizzare le opzioni disponibili e aggiornare i valori delle opzioni durante o dopo l'inizializzazione della primitiva.
  • Usa il metodo update() per applicare modifiche all'attributo options.
  • Se non specifichi un valore per un'opzione, le viene assegnato il valore speciale Unset e vengono usati i valori predefiniti del server.
  • L'attributo options è del tipo Python dataclass. Puoi usare il metodo integrato asdict per convertirlo in un dizionario.

Impostare le opzioni delle primitive​

Puoi impostare le opzioni durante l'inizializzazione della primitiva, dopo l'inizializzazione, oppure nel metodo run(). Consulta la sezione sulle regole di precedenza per capire cosa succede quando la stessa opzione viene specificata in più posti.

Inizializzazione della primitiva​

Puoi passare un'istanza della classe delle opzioni o un dizionario durante l'inizializzazione di una primitiva; la primitiva ne creerà una copia. Pertanto, modificare il dizionario originale o l'istanza delle opzioni non influisce sulle opzioni di proprietà della primitiva.

Classe delle opzioni​

Quando crei un'istanza della classe EstimatorV2 o SamplerV2, puoi passare un'istanza della classe delle opzioni. Tali opzioni verranno applicate quando usi run() per eseguire il calcolo. Specifica le opzioni nel seguente formato: options.option.sub-option.sub-sub-option = choice. Ad esempio: options.dynamical_decoupling.enable = True

Esempio:

SamplerV2 e EstimatorV2 hanno classi di opzioni separate (EstimatorOptions e SamplerOptions).

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime.options import EstimatorOptions

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

options = EstimatorOptions(
resilience_level=2,
resilience={"zne_mitigation": True, "zne": {"noise_factors": [1, 3, 5]}},
)

# or...
options = EstimatorOptions()
options.resilience_level = 2
options.resilience.zne_mitigation = True
options.resilience.zne.noise_factors = [1, 3, 5]

estimator = Estimator(mode=backend, options=options)

Dizionario​

Puoi specificare le opzioni come dizionario durante l'inizializzazione della primitiva.

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator

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

# Setting options during primitive initialization
estimator = Estimator(
backend,
options={
"resilience_level": 2,
"resilience": {
"zne_mitigation": True,
"zne": {"noise_factors": [1, 3, 5]},
},
},
)

Aggiornare le opzioni dopo l'inizializzazione​

Puoi specificare le opzioni nel formato primitive.options.option.sub-option.sub-sub-option = choice per sfruttare il completamento automatico, oppure usare il metodo update() per aggiornamenti in blocco.

Le classi di opzioni di SamplerV2 e EstimatorV2 (EstimatorOptions e SamplerOptions) non devono essere istanziate se stai impostando le opzioni dopo l'inizializzazione della primitiva.

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator

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

estimator = Estimator(mode=backend)

# Setting options after primitive initialization
# This uses auto-complete.
estimator.options.default_shots = 4000
# This does bulk update.
estimator.options.update(
default_shots=4000, resilience={"zne_mitigation": True}
)

Metodo Run()​

Gli unici valori che puoi passare a run() sono quelli definiti nell'interfaccia, ovvero shots per Sampler e precision per Estimator. Questo sovrascrive qualsiasi valore impostato per default_shots o default_precision per l'esecuzione corrente.

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit.circuit.library import random_iqp
from qiskit.transpiler import generate_preset_pass_manager

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

circuit1 = random_iqp(3)
circuit1.measure_all()
circuit2 = random_iqp(3)
circuit2.measure_all()

pass_manager = generate_preset_pass_manager(
optimization_level=3, backend=backend
)

transpiled1 = pass_manager.run(circuit1)
transpiled2 = pass_manager.run(circuit2)

sampler = Sampler(mode=backend)
# Default shots to use if not specified in run()
sampler.options.default_shots = 500
# Sample two circuits at 128 shots each.
sampler.run([transpiled1, transpiled2], shots=128)

# Sample two circuits with different numbers of shots.
# 100 shots is used for transpiled1 and 200 for transpiled.
sampler.run([(transpiled1, None, 100), (transpiled2, None, 200)])
<RuntimeJobV2('d5k96cn853es738djikg', 'sampler')>

Casi speciali​

Livello di resilienza (solo Estimator)​

Il livello di resilienza non è in realtà un'opzione che influisce direttamente sulla query della primitiva, ma specifica un insieme base di opzioni curate su cui costruire. In generale, il livello 0 disattiva tutta la mitigazione degli errori, il livello 1 abilita le opzioni per la mitigazione degli errori di misurazione, e il livello 2 abilita le opzioni per la mitigazione degli errori di gate e di misurazione.

Qualsiasi opzione che specifichi manualmente in aggiunta al livello di resilienza viene applicata sopra all'insieme base di opzioni definito dal livello di resilienza. Quindi, in linea di principio, potresti impostare il livello di resilienza a 1 ma poi disattivare la mitigazione della misurazione, anche se questo non è consigliato.

Nell'esempio seguente, impostare il livello di resilienza a 0 disattiva inizialmente zne_mitigation, ma estimator.options.resilience.zne_mitigation = True sovrascrive la configurazione rilevante di estimator.options.resilience_level = 0.

from qiskit_ibm_runtime import EstimatorV2, QiskitRuntimeService

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

estimator = EstimatorV2(backend)

estimator.options.default_shots = 100
estimator.options.resilience_level = 0
estimator.options.resilience.zne_mitigation = True

Shots (solo Sampler)​

Il metodo SamplerV2.run accetta due argomenti: una lista di PUB, ognuno dei quali può specificare un valore di shots specifico per il PUB, e un argomento keyword shots. Questi valori di shots fanno parte dell'interfaccia di esecuzione del Sampler e sono indipendenti dalle opzioni del Sampler Runtime. Hanno la precedenza su qualsiasi valore specificato come opzione, per conformarsi all'astrazione del Sampler.

Tuttavia, se shots non è specificato da nessun PUB né nell'argomento keyword di run (o se sono tutti None), viene usato il valore di shots dalle opzioni, in particolare default_shots.

In sintesi, questo è l'ordine di precedenza per specificare gli shots nel Sampler, per un particolare PUB:

  1. Se il PUB specifica shots, usa quel valore.
  2. Se l'argomento keyword shots è specificato in run, usa quel valore.
  3. Se num_randomizations e shots_per_randomization sono specificati come opzioni di twirling, gli shots sono il prodotto di quei valori.
  4. Se sampler.options.default_shots è specificato, usa quel valore.

Quindi, se gli shots sono specificati in tutti i posti possibili, viene usato quello con la priorità più alta (shots specificati nel PUB).

Precisione (solo Estimator)​

La precisione è analoga agli shots, descritti nella sezione precedente, eccetto che le opzioni dell'Estimator contengono sia default_shots che default_precision. Inoltre, poiché il gate-twirling è abilitato per impostazione predefinita, il prodotto di num_randomizations e shots_per_randomization ha la precedenza su quelle due opzioni.

Nello specifico, per un particolare PUB dell'Estimator:

  1. Se il PUB specifica la precisione, usa quel valore.
  2. Se l'argomento keyword precision è specificato in run, usa quel valore.
  3. Se num_randomizations e shots_per_randomization sono specificati come opzioni di twirling (abilitate per impostazione predefinita), usa il loro prodotto per controllare la quantità di dati.
  4. Se estimator.options.default_shots è specificato, usa quel valore per controllare la quantità di dati.
  5. Se estimator.options.default_precision è specificato, usa quel valore.

Ad esempio, se la precisione è specificata in tutti e quattro i posti, viene usato quello con la priorità più alta (precisione specificata nel PUB).

nota

La precisione scala in modo inversamente proporzionale all'utilizzo. Vale a dire, minore è la precisione, più tempo QPU è necessario per l'esecuzione.

Opzioni comunemente usate​

Sono disponibili molte opzioni, ma le seguenti sono le più comunemente usate:

Shots​

Per alcuni algoritmi, impostare un numero specifico di shots è una parte fondamentale delle loro routine. Gli shots (o la precisione) possono essere specificati in più posti. Vengono prioritizzati come segue:

Per qualsiasi PUB del Sampler:

  1. Shots con valore intero contenuti nel PUB
  2. Il valore run(...,shots=val)
  3. Il valore options.default_shots

Per qualsiasi PUB dell'Estimator:

  1. Precisione con valore float contenuta nel PUB
  2. Il valore run(...,precision=val)
  3. Il valore options.default_shots
  4. Il valore options.default_precision

Esempio:

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit.circuit.library import random_iqp
from qiskit.transpiler import generate_preset_pass_manager

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

circuit1 = random_iqp(3)
circuit1.measure_all()
circuit2 = random_iqp(3)
circuit2.measure_all()

pass_manager = generate_preset_pass_manager(
optimization_level=3, backend=backend
)

transpiled1 = pass_manager.run(circuit1)
transpiled2 = pass_manager.run(circuit2)

# Setting shots during primitive initialization
sampler = Sampler(mode=backend, options={"default_shots": 4096})

# Setting options after primitive initialization
# This uses auto-complete.
sampler.options.default_shots = 2000

# This does bulk update. The value for default_shots is overridden if you specify shots with run() or in the PUB.
sampler.options.update(
default_shots=1024, dynamical_decoupling={"sequence_type": "XpXm"}
)

# Sample two circuits at 128 shots each.
sampler.run([transpiled1, transpiled2], shots=128)
<RuntimeJobV2('d5k96icjt3vs73ds5t0g', 'sampler')>

Tempo massimo di esecuzione​

Il tempo massimo di esecuzione (max_execution_time) limita quanto a lungo può girare un job. Se un job supera questo limite di tempo, viene annullato forzatamente. Questo valore si applica ai job singoli, indipendentemente dal fatto che vengano eseguiti in modalità job, sessione o batch.

Il valore è impostato in secondi, basato sul tempo quantistico (non sul tempo di orologio), che è la quantità di tempo in cui il QPU è dedicato all'elaborazione del tuo job. Viene ignorato quando si usa la modalità di test locale poiché tale modalità non utilizza il tempo quantistico.

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator

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

estimator = Estimator(mode=backend)

estimator.options.max_execution_time = 2500

Disattivare tutta la mitigazione e la soppressione degli errori​

Puoi disattivare tutta la mitigazione e la soppressione degli errori se stai, ad esempio, conducendo ricerche sulle tue tecniche di mitigazione. Per farlo, per EstimatorV2, imposta resilience_level = 0. Per SamplerV2 non è necessaria alcuna modifica poiché nessuna opzione di mitigazione o soppressione degli errori è abilitata per impostazione predefinita.

Esempio:

Disattiva tutta la mitigazione e la soppressione degli errori nell'Estimator.

from qiskit_ibm_runtime import EstimatorV2 as Estimator, QiskitRuntimeService

# Define the service. This allows you to access IBM QPU.
service = QiskitRuntimeService()

# Get a backend
backend = service.least_busy(operational=True, simulator=False)

# Define Estimator
estimator = Estimator(backend)

options = estimator.options

# Turn off all error mitigation and suppression
options.resilience_level = 0

Passi successivi​

Raccomandazioni