Portuguese
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

Nota

Esta página foi gerada, a partir do tutorials/algorithms/03_vqe_simulation_with_noise.ipynb.

VQE com Qiskit Aer Primitives

Este notebook demonstra como aproveitar o Qiskit Aer Primitives para executar simulações silenciosas e ruidosas localmente. O Qiskit Aer não apenas permite que você defina seu próprio modelo de ruído personalizado, mas também crie facilmente um modelo de ruído com base nas propriedades de um dispositivo quântico real. Este notebook mostrará um exemplo do último, para ilustrar o fluxo de trabalho geral da execução de algoritmos com simuladores locais de ruído.

Para mais informações sobre o modelo de ruído Qiskit Aer, você pode consultar a documentação do Qiskit Aer, bem como o tutorial para construir modelos de ruído.

O algoritmo escolhido é mais uma vez o VQE, onde a tarefa consiste em encontrar a energia mínima (estado fundamental) de um hamiltoniano. Conforme mostrado nos tutoriais anteriores, o VQE usa um operador qubit como entrada. Aqui, você pegará um conjunto de operadores de Pauli que foram originalmente calculados pelo Qiskit Nature para a molécula H2, usando a classe SparsePauliOp.

[1]:
from qiskit.quantum_info import SparsePauliOp

H2_op = SparsePauliOp.from_list(
    [
        ("II", -1.052373245772859),
        ("IZ", 0.39793742484318045),
        ("ZI", -0.39793742484318045),
        ("ZZ", -0.01128010425623538),
        ("XX", 0.18093119978423156),
    ]
)

print(f"Number of qubits: {H2_op.num_qubits}")
Number of qubits: 2

Como o problema acima ainda é facilmente tratável classicamente, você pode usar NumPyMinimumEigensolver para calcular um valor de referência para comparar os resultados posteriormente.

[2]:
from qiskit.algorithms import NumPyMinimumEigensolver
from qiskit.opflow import PauliSumOp

numpy_solver = NumPyMinimumEigensolver()
result = numpy_solver.compute_minimum_eigenvalue(operator=PauliSumOp(H2_op))
ref_value = result.eigenvalue.real
print(f"Reference value: {ref_value:.5f}")
Reference value: -1.85728

Os exemplos a seguir usarão o mesmo ansatz e otimizador, definidos da seguinte forma:

[3]:
# define ansatz and optimizer
from qiskit.circuit.library import TwoLocal
from qiskit.algorithms.optimizers import SPSA

iterations = 125
ansatz = TwoLocal(rotation_blocks="ry", entanglement_blocks="cz")
spsa = SPSA(maxiter=iterations)

Desempenho sem ruído

Vamos primeiro executar o VQE no simulador Aer padrão sem adicionar ruído, com uma seed fixa para a execução e transpilação para obter resultados reprodutíveis. Este resultado deve ser relativamente próximo ao valor de referência do cálculo exato.

[4]:
# define callback
# note: Re-run this cell to restart lists before training
counts = []
values = []


def store_intermediate_result(eval_count, parameters, mean, std):
    counts.append(eval_count)
    values.append(mean)
[5]:
# define Aer Estimator for noiseless statevector simulation
from qiskit.utils import algorithm_globals
from qiskit_aer.primitives import Estimator as AerEstimator

seed = 170
algorithm_globals.random_seed = seed

noiseless_estimator = AerEstimator(
    run_options={"seed": seed, "shots": 1024},
    transpile_options={"seed_transpiler": seed},
)
[6]:
# instantiate and run VQE
from qiskit.algorithms.minimum_eigensolvers import VQE

vqe = VQE(
    noiseless_estimator, ansatz, optimizer=spsa, callback=store_intermediate_result
)
result = vqe.compute_minimum_eigenvalue(operator=H2_op)

print(f"VQE on Aer qasm simulator (no noise): {result.eigenvalue.real:.5f}")
print(
    f"Delta from reference energy value is {(result.eigenvalue.real - ref_value):.5f}"
)
VQE on Aer qasm simulator (no noise): -1.84322
Delta from reference energy value is 0.01406

Você capturou os valores de energia acima durante a convergência, então você pode acompanhar o processo no gráfico abaixo.

[7]:
import pylab

pylab.rcParams["figure.figsize"] = (12, 4)
pylab.plot(counts, values)
pylab.xlabel("Eval count")
pylab.ylabel("Energy")
pylab.title("Convergence with no noise")
[7]:
Text(0.5, 1.0, 'Convergence with no noise')
../../_images/tutorials_algorithms_03_vqe_simulation_with_noise_12_1.png

Desempenho com ruído

Agora, vamos adicionar ruído à nossa simulação. Em particular, você extrairá um modelo de ruído de um dispositivo (falso). Conforme comentado na introdução, também é possível criar do zero modelos de ruído personalizados, mas isso está além do escopo deste notebook.

Primeiro, você precisa obter um back-end do dispositivo real e, a partir de sua configuração e propriedades, você pode configurar um mapa de acoplamento e um modelo de ruído para corresponder ao dispositivo. Observação: você também pode usar este mapa de acoplamento como o mapa de emaranhamento para a forma variacional, se desejar.

[8]:
from qiskit_aer.noise import NoiseModel
from qiskit.providers.fake_provider import FakeVigo

# fake providers contain data from real IBM Quantum devices stored in Qiskit Terra,
# and are useful for extracting realistic noise models.
device = FakeVigo()

coupling_map = device.configuration().coupling_map
noise_model = NoiseModel.from_backend(device)

print(noise_model)
NoiseModel:
  Basis gates: ['cx', 'id', 'rz', 'sx', 'x']
  Instructions with noise: ['id', 'measure', 'sx', 'x', 'cx']
  Qubits with noise: [0, 1, 2, 3, 4]
  Specific qubit errors: [('id', (0,)), ('id', (1,)), ('id', (2,)), ('id', (3,)), ('id', (4,)), ('sx', (0,)), ('sx', (1,)), ('sx', (2,)), ('sx', (3,)), ('sx', (4,)), ('x', (0,)), ('x', (1,)), ('x', (2,)), ('x', (3,)), ('x', (4,)), ('cx', (3, 4)), ('cx', (4, 3)), ('cx', (3, 1)), ('cx', (1, 3)), ('cx', (1, 2)), ('cx', (2, 1)), ('cx', (0, 1)), ('cx', (1, 0)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('measure', (4,))]

Uma vez que o modelo de ruído é definido, você pode rodar VQE usando um Aer Estimator, onde você pode passar o modelo de ruído para o simulador subjacente usando o dicionário backend_options. Observe que esta simulação levará mais tempo do que a sem ruído.

[9]:
noisy_estimator = AerEstimator(
    backend_options={
        "method": "density_matrix",
        "coupling_map": coupling_map,
        "noise_model": noise_model,
    },
    run_options={"seed": seed, "shots": 1024},
    transpile_options={"seed_transpiler": seed},
)

Em vez de definir uma nova instância da classe VQE, agora você pode simplesmente atribuir um novo estimador à nossa instância VQE anterior. Como o método callback será reutilizado, você também precisará reiniciar as variáveis counts e values para poder traçar o gráfico de convergência mais tarde.

[10]:
# re-start callback variables
counts = []
values = []
[11]:
vqe.estimator = noisy_estimator

result1 = vqe.compute_minimum_eigenvalue(operator=H2_op)

print(f"VQE on Aer qasm simulator (with noise): {result1.eigenvalue.real:.5f}")
print(
    f"Delta from reference energy value is {(result1.eigenvalue.real - ref_value):.5f}"
)
VQE on Aer qasm simulator (with noise): -1.74645
Delta from reference energy value is 0.11083
[12]:
if counts or values:
    pylab.rcParams["figure.figsize"] = (12, 4)
    pylab.plot(counts, values)
    pylab.xlabel("Eval count")
    pylab.ylabel("Energy")
    pylab.title("Convergence with noise")
../../_images/tutorials_algorithms_03_vqe_simulation_with_noise_20_0.png

Resumo

Neste tutorial, você comparou três cálculos para o estado fundamental da molécula de H2. Primeiro, você produziu um valor de referência usando um autosolver mínimo clássico. Em seguida, você executou VQE usando o Qiskit Aer Estimator com 1024 disparos. Finalmente, você extraiu um modelo de ruído de um back-end e o usou para definir um novo Estimator para simulações de ruído. Os resultados são:

[13]:
print(f"Reference value: {ref_value:.5f}")
print(f"VQE on Aer qasm simulator (no noise): {result.eigenvalue.real:.5f}")
print(f"VQE on Aer qasm simulator (with noise): {result1.eigenvalue.real:.5f}")
Reference value: -1.85728
VQE on Aer qasm simulator (no noise): -1.84322
VQE on Aer qasm simulator (with noise): -1.74645

Você pode notar que, embora o resultado da simulação sem ruído esteja mais próximo do valor de referência exato, ainda há uma diferença. Isso se deve ao ruído de amostragem, introduzido ao limitar o número de disparos a 1024. Um número maior de disparos diminuiria esse erro de amostragem e diminuiria a diferença entre esses dois valores.

Quanto ao ruído introduzido por dispositivos reais (ou modelos de ruído simulados), ele pode ser resolvido por meio de uma ampla variedade de técnicas de mitigação de erros. Os Qiskit Runtime Primitives habilitaram a mitigação de erros através da opção resilience_level. Esta opção está atualmente disponível para simuladores remotos e backends reais acessados por meio dos Primitivos de tempo de execução, você pode consultar este tutorial para mais informações.

[14]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.22.2
qiskit-aer0.11.1
qiskit-ignis0.7.1
qiskit-ibmq-provider0.19.2
qiskit0.39.2
System information
Python version3.10.2
Python compilerClang 13.0.0 (clang-1300.0.29.30)
Python buildv3.10.2:a58ebcc701, Jan 13 2022 14:50:16
OSDarwin
CPUs8
Memory (Gb)64.0
Fri Nov 18 01:03:00 2022 CET

This code is a part of Qiskit

© Copyright IBM 2017, 2022.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.