Pular para o conteúdo principal

Especificar opções

Versões dos pacotes

O código nesta página foi desenvolvido usando os seguintes requisitos. Recomendamos usar estas versões ou versões mais recentes.

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

Você pode usar opções para personalizar as primitivas Estimator e Sampler. Esta seção se concentra em como especificar opções das primitivas do Qiskit Runtime. Embora a interface do método run() das primitivas seja comum a todas as implementações, suas opções não são. Consulte as referências de API correspondentes para informações sobre as opções de qiskit.primitives e qiskit_aer.primitives.

Observações sobre como especificar opções nas primitivas:

  • SamplerV2 e EstimatorV2 possuem classes de opções separadas. Você pode ver as opções disponíveis e atualizar os valores das opções durante ou após a inicialização da primitiva.
  • Use o método update() para aplicar alterações ao atributo options.
  • Se você não especificar um valor para uma opção, ela recebe um valor especial de Unset e os padrões do servidor são usados.
  • O atributo options é do tipo Python dataclass. Você pode usar o método integrado asdict para convertê-lo em um dicionário.

Definir opções da primitiva

Você pode definir opções ao inicializar a primitiva, após inicializá-la ou no método run(). Consulte a seção de regras de precedência para entender o que acontece quando a mesma opção é especificada em vários lugares.

Inicialização da primitiva

Você pode passar uma instância da classe de opções ou um dicionário ao inicializar uma primitiva, que então faz uma cópia dessas opções. Assim, alterar o dicionário original ou a instância de opções não afeta as opções pertencentes às primitivas.

Classe de opções

Ao criar uma instância da classe EstimatorV2 ou SamplerV2, você pode passar uma instância da classe de opções. Essas opções serão então aplicadas quando você usar run() para realizar o cálculo. Especifique as opções neste formato: options.option.sub-option.sub-sub-option = choice. Por exemplo: options.dynamical_decoupling.enable = True

Exemplo:

SamplerV2 e EstimatorV2 possuem classes de opções separadas (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)

Dicionário

Você pode especificar opções como um dicionário ao inicializar a 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]},
},
},
)

Atualizar opções após a inicialização

Você pode especificar as opções neste formato: primitive.options.option.sub-option.sub-sub-option = choice para aproveitar o autocompletar, ou usar o método update() para fazer atualizações em lote.

As classes de opções de SamplerV2 e EstimatorV2 (EstimatorOptions e SamplerOptions) não precisam ser instanciadas se você estiver definindo opções após inicializar a 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}
)

Método Run()

Os únicos valores que você pode passar para run() são aqueles definidos na interface. Ou seja, shots para o Sampler e precision para o Estimator. Isso substitui qualquer valor definido para default_shots ou default_precision na execução atual.

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

Casos especiais

Nível de resiliência (somente Estimator)

O nível de resiliência não é, na verdade, uma opção que impacta diretamente a consulta à primitiva, mas especifica um conjunto base de opções curadas para se basear. Em geral, o nível 0 desativa toda a mitigação de erros, o nível 1 ativa opções para mitigação de erros de medição e o nível 2 ativa opções para mitigação de erros de gate e de medição.

Quaisquer opções que você especificar manualmente além do nível de resiliência são aplicadas sobre o conjunto base de opções definido pelo nível de resiliência. Portanto, em princípio, você poderia definir o nível de resiliência como 1, mas ainda assim desativar a mitigação de medição, embora isso não seja recomendado.

No exemplo a seguir, definir o nível de resiliência como 0 inicialmente desativa zne_mitigation, mas estimator.options.resilience.zne_mitigation = True substitui a configuração relevante de 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 (somente Sampler)

O método SamplerV2.run aceita dois argumentos: uma lista de PUBs, cada um dos quais pode especificar um valor de shots específico para o PUB, e um argumento de palavra-chave shots. Esses valores de shots fazem parte da interface de execução do Sampler e são independentes das opções do Sampler do Runtime. Eles têm precedência sobre quaisquer valores especificados como opções, a fim de cumprir com a abstração do Sampler.

No entanto, se shots não for especificado por nenhum PUB nem no argumento de palavra-chave do run (ou se todos forem None), então o valor de shots das opções é usado, especialmente default_shots.

Para resumir, esta é a ordem de precedência para especificar shots no Sampler, para qualquer PUB em particular:

  1. Se o PUB especifica shots, use esse valor.
  2. Se o argumento de palavra-chave shots é especificado em run, use esse valor.
  3. Se num_randomizations e shots_per_randomization são especificados como opções de twirling, os shots são o produto desses valores.
  4. Se sampler.options.default_shots é especificado, use esse valor.

Portanto, se shots forem especificados em todos os lugares possíveis, o de maior precedência (shots especificados no PUB) é usado.

Precisão (somente Estimator)

A precisão é análoga aos shots, descritos na seção anterior, exceto que as opções do Estimator contêm tanto default_shots quanto default_precision. Além disso, como o gate-twirling está habilitado por padrão, o produto de num_randomizations e shots_per_randomization tem precedência sobre essas duas opções.

Especificamente, para qualquer PUB do Estimator em particular:

  1. Se o PUB especifica precisão, use esse valor.
  2. Se o argumento de palavra-chave precision é especificado em run, use esse valor.
  3. Se num_randomizations e shots_per_randomization são especificados como opções de twirling (habilitadas por padrão), use o produto deles para controlar a quantidade de dados.
  4. Se estimator.options.default_shots é especificado, use esse valor para controlar a quantidade de dados.
  5. Se estimator.options.default_precision é especificado, use esse valor.

Por exemplo, se a precisão for especificada em todos os quatro lugares, o de maior precedência (precisão especificada no PUB) é usado.

nota

A precisão escala inversamente com o uso. Ou seja, quanto menor a precisão, mais tempo de QPU é necessário para executar.

Opções mais usadas

Há muitas opções disponíveis, mas as seguintes são as mais usadas:

Shots

Para alguns algoritmos, definir um número específico de shots é uma parte central de suas rotinas. Shots (ou precisão) podem ser especificados em vários lugares. Eles são priorizados da seguinte forma:

Para qualquer PUB do Sampler:

  1. Shots com valor inteiro contidos no PUB
  2. O valor run(...,shots=val)
  3. O valor options.default_shots

Para qualquer PUB do Estimator:

  1. Precisão com valor float contida no PUB
  2. O valor run(...,precision=val)
  3. O valor options.default_shots
  4. O valor options.default_precision

Exemplo:

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 máximo de execução

O tempo máximo de execução (max_execution_time) limita por quanto tempo um job pode ser executado. Se um job exceder esse limite de tempo, ele é cancelado à força. Esse valor se aplica a jobs individuais, independentemente de serem executados no modo job, sessão ou batch.

O valor é definido em segundos, com base no tempo quântico (não no tempo de relógio de parede), que é a quantidade de tempo que o QPU dedica ao processamento do seu job. Ele é ignorado ao usar o modo de teste local, pois esse modo não usa tempo quântico.

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

Desativar toda a mitigação e supressão de erros

Você pode desativar toda a mitigação e supressão de erros se estiver, por exemplo, realizando pesquisas sobre suas próprias técnicas de mitigação. Para isso, no EstimatorV2, defina resilience_level = 0. Para o SamplerV2, nenhuma alteração é necessária porque nenhuma opção de mitigação ou supressão de erros está habilitada por padrão.

Exemplo:

Desative toda a mitigação e supressão de erros no 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

Próximos passos

Recomendações