Note
Cette page a été générée à partir de tutorials/algorithms/03_vqe_simulation_with_noise.ipynb.
VQE avec Qiskit Aer Primitives¶
Ce notebook montre comment tirer parti des Qiskit Aer Primitives pour exécuter localement des simulations sans bruit et avec bruit. Qiskit Aer vous permet non seulement de définir votre propre modèle de bruit personnalisé, mais aussi de créer un modèle de bruit basé sur les propriétés d’un vrai appareil quantique facilement. Ce nootbook montrera un exemple de ce dernier, pour illustrer le workflow général des algorithmes d’exécutions avec des simulateurs locaux de bruit.
Pour plus d’informations sur le modèle de bruit Qiskit Aer, vous pouvez consulter la documentation de Qiskit Aer. ainsi que le tutoriel pour construire des modèles de bruit.
L’algorithme choisi est encore une fois le VQE, où la tâche consiste à trouver l’énergie minimale (état fondamental) d’un hamiltonien. Comme indiqué dans les tutoriels précédents, le VQE utilise un opérateur de qubit en entrée. Ici, vous prenez un ensemble d’opérateurs de Pauli qui ont été initialement calculés par Qiskit Nature pour la molécule H2, en utilisant la 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
Comme le problème ci-dessus est toujours facilement tractable classiquement, vous pouvez utiliser NumPyMinimumEigensolver
pour calculer une valeur de référence pour les résultats plus tard.
[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
Les exemples suivants utiliseront tous les mêmes ansatz et optimiseur, défini comme suit :
[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)
Performance sans bruit¶
Tout d’abord, exécutons le VQE
avec le simulateur Aer par défaut sans ajouter de bruit, avec une graine fixe pour l’exécution et effectuons la transpilation pour obtenir des résultats reproductibles. Ce résultat devrait être relativement proche de la valeur de référence du calcul exact.
[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
Vous avez capturé les valeurs énergétiques ci-dessus lors de la convergence, vous pouvez donc suivre le processus dans le graphique ci-dessous.
[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')

Performance avec bruit¶
Maintenant, ajoutons du bruit à notre simulation. En particulier, vous allez extraire un modèle de bruit à partir d’un (faux) appareil. Comme indiqué dans l’introduction, il est également possible de créer des modèles de bruit personnalisés à partir de zéro, mais cette tâche dépasse le cadre de ce notebook.
Tout d’abord, voud devez obtenir un système d’execurtion réel et nous pouvons configurer une carte de couplage et un modèle de bruit à partir de sa configuration
et de ses properties
pour qu’il corresponde à l’appareil. Remarque : Vous pouvez aussi utiliser cette carte de couplage comme carte d’intrication pour la forme variationnelle si vous le choisissez.
[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,))]
Une fois le modèle de bruit est défini, vous pouvez exécuter le VQE
en utilisant le Estimator
d’Aer, où vous pouvez passer le modèle de bruit au simulateur sous-jacent en utilisant le dictionnaire backend_options
. Veuillez noter que cette simulation prendra plus de temps que la simulation sans bruit.
[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},
)
Au lieu de définir une nouvelle instance de la classe VQE
, vous pouvez maintenant simplement assigner un nouvel estimateur à notre instance VQE
précédente. Comme la méthode de rappel sera réutilisée, vous aurez également besoin de relancer les variables counts
et values
pour pouvoir ensuite tracer le graphique de convergence.
[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")

En résumé¶
Dans ce tutoriel, vous avez comparé trois calculs pour l’état fondamental de la molécule H2. Tout d’abord, vous avez produit une valeur de référence en utilisant un « eigensolver » classique. Ensuite, vous avez exécuté le VQE
en utilisant le Qiskit Aer Estimator
avec 1024 coups. Enfin, vous avez extrait un modèle de bruit d’un backend et vous l’avez utilisé pour définir un nouveau Estimator
pour des simulations avec bruit. Les résultats sont les suivants :
[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
Vous pouvez remarquer que, si le résultat de la simulation sans bruit est plus proche de la valeur de référence exacte, il y a encore une différence. Ceci est dû au bruit d’échantillonnage, introduit en limitant le nombre de coups à 1024. Un plus grand nombre de coups diminuerait cette erreur d’échantillonnage et comblerait l’écart entre ces deux valeurs.
Quant au bruit généré par des appareils réels (ou des modèles de bruit simulés), il peut être traité par une grande variété de techniques de réduction d’erreur. Le Qiskit Runtime Primitives a activé l’atténuation des erreurs via l’option resilience_level
. Cette option est actuellement disponible pour les simulateurs distants et les backends réels accessibles via Runtime Primitives, vous pouvez vous référer à ce tutoriel pour plus d’informations.
[14]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.22.2 |
qiskit-aer | 0.11.1 |
qiskit-ignis | 0.7.1 |
qiskit-ibmq-provider | 0.19.2 |
qiskit | 0.39.2 |
System information | |
Python version | 3.10.2 |
Python compiler | Clang 13.0.0 (clang-1300.0.29.30) |
Python build | v3.10.2:a58ebcc701, Jan 13 2022 14:50:16 |
OS | Darwin |
CPUs | 8 |
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.