Simulation exacte et bruitée avec les primitives Qiskit Aer
Versions des packages
Le code de cette page a été développé avec les prérequis suivants. Nous recommandons d'utiliser ces versions ou des versions plus récentes.
qiskit[all]~=2.3.0
qiskit-aer~=0.17
La simulation exacte avec les primitives Qiskit montre comment utiliser les primitives de référence incluses dans Qiskit pour effectuer une simulation exacte de circuits quantiques. Les processeurs quantiques actuels sont sujets à des erreurs, ou bruits, de sorte que les résultats d'une simulation exacte ne reflètent pas nécessairement ce que tu obtiendrais en exécutant les circuits sur du matériel réel. Bien que les primitives de référence de Qiskit ne prennent pas en charge la modélisation du bruit, Qiskit Aer inclut des implémentations des primitives qui le font. Qiskit Aer est un simulateur de circuits quantiques haute performance que tu peux utiliser à la place des primitives de référence pour de meilleures performances et plus de fonctionnalités. Il fait partie du Qiskit Ecosystem. Dans cet article, nous montrons comment utiliser les primitives Qiskit Aer pour la simulation exacte et bruitée.
qiskit-aerv0.14 ou une version ultérieure est requise.- Bien que les primitives Qiskit Aer implémentent les interfaces des primitives, elles ne proposent pas les mêmes options que les primitives Qiskit Runtime. Le niveau de résilience, par exemple, n'est pas disponible avec les primitives Qiskit Aer.
- Consulte la documentation d'AerSimulator pour plus de détails sur les options de méthode de simulation prises en charge par Aer.
Pour explorer la simulation exacte et bruitée, crée un exemple de circuit sur huit qubits :
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2
n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")
Ce circuit contient des paramètres représentant les angles de rotation pour les portes et . Lors de la simulation de ce circuit, nous devons spécifier des valeurs explicites pour ces paramètres. Dans la cellule suivante, nous définissons certaines valeurs pour ces paramètres et utilisons la primitive Estimator de Qiskit Aer pour calculer la valeur d'espérance exacte de l'observable .
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator
observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters
exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602
Maintenant, initialisons un modèle de bruit qui inclut une erreur de dépolarisation de 2 % sur chaque porte CX. En pratique, les erreurs provenant des portes à deux qubits — ici les portes CX — constituent la principale source d'erreur lors de l'exécution d'un circuit. Consulte Construire des modèles de bruit pour un aperçu de la construction de modèles de bruit dans Qiskit Aer.
Dans la cellule suivante, nous construisons un Estimator qui intègre ce modèle de bruit et l'utilisons pour calculer la valeur d'espérance de l'observable.
from qiskit_aer.noise import NoiseModel, depolarizing_error
noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)
noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143528
Comme tu peux le constater, la valeur d'espérance en présence du bruit est assez éloignée de la valeur correcte. En pratique, tu peux employer diverses techniques d'atténuation des erreurs pour contrecarrer les effets du bruit, mais la discussion de ces techniques dépasse le cadre de cet article.
Pour avoir une idée très approximative de la façon dont le bruit affecte le résultat final, considère notre modèle de bruit, qui ajoute une erreur de dépolarisation de 2 % à chaque porte CX. Une erreur de dépolarisation avec une probabilité est définie comme un canal quantique qui agit de la façon suivante sur une matrice densité :
où est le nombre de qubits, ici 2. Autrement dit, avec une probabilité , l'état est remplacé par l'état complètement mixte, et l'état est préservé avec une probabilité . Après applications du canal de dépolarisation, la probabilité que l'état soit préservé serait . Par conséquent, nous nous attendons à ce que la probabilité de conserver l'état correct à la fin de la simulation diminue de façon exponentielle avec le nombre de portes CX dans notre circuit.
Comptons le nombre de portes CX dans notre circuit et calculons . Nous appelons count_ops pour obtenir un dictionnaire qui associe les noms des portes à leurs nombres d'occurrences, et récupérons l'entrée pour la porte CX.
cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923
Cette valeur, 65 %, donne une estimation approximative de la probabilité que notre état final soit correct. C'est une estimation conservatrice, car elle ne tient pas compte de l'état initial de la simulation.
La cellule de code suivante montre comment utiliser la primitive Sampler de Qiskit Aer pour échantillonner depuis le circuit bruité. Nous devons ajouter des mesures au circuit avant de l'exécuter avec la primitive Sampler.
from qiskit_aer.primitives import SamplerV2 as Sampler
measured_circuit = circuit.copy()
measured_circuit.measure_all()
noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00100000': 1,
'00000000': 65,
'10101000': 1,
'10000000': 5,
'00001000': 1,
'00000110': 2,
'11110010': 1,
'00000011': 3,
'01010000': 3,
'11000000': 3,
'01111000': 1,
'01000000': 2,
'00000010': 1,
'01100000': 1,
'00011000': 1,
'00111100': 1,
'00010100': 1,
'00001111': 1,
'00110000': 1,
'01100101': 1,
'00000100': 1,
'10100000': 1,
'00000001': 1,
'11010000': 1}
Prochaines étapes
- Pour simuler des circuits petits et simples, consulte La simulation exacte avec les primitives Qiskit.
- Consulte la documentation de Qiskit Aer.