Explorer l'incertitude
Pour ce module Qiskit en classe, les étudiant·e·s doivent disposer d'un environnement Python fonctionnel avec les packages suivants installés :
qiskitv2.1.0 ou plus récentqiskit-ibm-runtimev0.40.1 ou plus récentqiskit-aerv0.17.0 ou plus récentqiskit.visualizationnumpypylatexenc
Pour configurer et installer les packages ci-dessus, consulte le guide Installer Qiskit. Pour exécuter des jobs sur de vrais ordinateurs quantiques, les étudiant·e·s devront créer un compte IBM Quantum® en suivant les étapes du guide Configurer ton compte IBM Cloud.
Ce module a été testé et a utilisé 8 minutes de temps QPU. Il s'agit d'une estimation uniquement. Ton utilisation réelle peut varier. Deux calculs chronophages sont signalés comme tels dans les commentaires d'en-tête et peuvent être effectués sur des simulateurs si les étudiant·e·s manquent de temps QPU. Sans ces deux calculs, le module ne requiert qu'environ ~30 secondes de temps QPU.
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
Regarde la présentation du module par Dr. Katie McCormick ci-dessous, ou clique ici pour la regarder sur YouTube.
Introduction
Tu as probablement entendu parler du principe d'incertitude, même en dehors de tes cours de physique. Une reformulation courante de l'incertitude dans le langage quotidien est : « En observant quelque chose, tu l'influences. » C'est certainement vrai. Mais une façon plus physique de décrire l'incertitude est qu'il existe certaines observables physiques qui présentent une incompatibilité les empêchant d'être toutes deux connues simultanément avec une précision arbitraire. De nombreux étudiant·e·s rencontrent pour la première fois la paire de variables incompatibles et , c'est-à-dire la position le long d'un axe appelé l'axe , et la quantité de mouvement lin éaire dans cette direction, respectivement. Pour ces variables, la contrainte d'incertitude s'écrit Ici, est appelé l'« incertitude sur », qui a la même définition que l'écart-type en statistiques, et peut être défini comme est défini de la même façon. Ici, nous ne dériverons pas cette relation d'incertitude ; nous ferons remarquer qu'elle est cohérente avec notre compréhension des ondes classiques. C'est-à-dire qu'une onde avec une seule fréquence parfaite et une longueur d'onde s'étendrait indéfiniment en tant que sinusoïde parfaite. En mécanique quantique, cela correspondrait à connaître parfaitement la quantité de mouvement selon l'hypothèse de de Broglie : . Mais pour savoir se trouve une particule ondulatoire, l'onde qui la décrit doit devenir plus fortement concentrée dans l'espace, comme une gaussienne très étroite, par exemple. Nous savons que nous pouvons exprimer toute fonction continue, y compris de telles fonctions d'onde fortement concentrées, comme une série de Fourier de fonctions sinusoïdales de différentes longueurs d'onde. Mais à mesure que la fonction d'onde devient plus fortement concentrée (et que la position est mieux connue), nous aurons besoin de plus de termes dans la série de Fourier, ce qui signifie un mélange de plus de longueurs d'onde (et donc, en mécanique quantique, de plus de valeurs de quantité de mouvement).
Dit plus simplement : un état avec une quantité de mouvement bien définie (une sinusoïde parfaite dans l'espace) a une position très incertaine. Un état avec une position bien définie (comme une distribution de Dirac delta) a une quantité de mouvement très incertaine.
Il existe d'autres variables présentant une telle incompatibilité. Par exemple, le spin d'une particule peut avoir une projection bien définie le long d'un axe, mais alors on ne sait rien de la projection sur un axe orthogonal. Par exemple, l'état (pour un qubit ou une particule de spin 1/2) a une projection définie le long de l'axe (de 1 dans le contexte d'un qubit, et de dans le contexte d'une particule de spin 1/2). Mais cet état peut s'écrire comme une superposition de deux états ayant chacun une projection bien définie sur l'axe : ou de façon équivalente a une projection bien définie sur , tout comme . Donc si on spécifie la projection d'un état le long de l'axe , on ne connaît pas la projection le long de l'axe . Et si on spécifie la projection sur l'axe , on ne connaît pas la projection le long de . Il existe de légères différences quand on aborde cela dans le contexte du spin et dans celui des qubits. Mais en général, les états propres des matrices de Pauli ont une relation intéressante que nous pouvons explorer. Tout au long de cette leçon, nous vérifierons expérimentalement notre intuition sur l'incertitude dans ces variables incompatibles, et nous vérifierons que les relations d'incertitude sont respectées sur les ordinateurs quantiques IBM®.
Vérification simple de l'intuition
Dans cette première expérience et tout au long du module, nous utiliserons un cadre de travail pour l'informatique quantique connu sous le nom de « Qiskit patterns », qui décompose les flux de travail en les étapes suivantes :
- Étape 1 : Mapper les entrées classiques vers un problème quantique
- Étape 2 : Optimiser le problème pour l'exécution quantique
- Étape 3 : Exécuter à l'aide des primitives Qiskit Runtime
- Étape 4 : Post-traitement et analyse classique
Nous suivrons généralement ces étapes, même si nous ne les étiquetterons pas toujours explicitement.
Commençons par charger quelques packages nécessaires, y compris les primitives Runtime. Nous sélectionnerons également l'ordinateur quantique le moins chargé disponible.
Il y a du code ci-dessous pour sauvegarder tes identifiants lors de la première utilisation. Assure-toi de supprimer ces informations du notebook après les avoir sauvegardées dans ton environnement, afin que tes identifiants ne soient pas accidentellement partagés lorsque tu partages le notebook. Consulte Configurer ton compte IBM Cloud et Initialiser le service dans un environnement non fiable pour plus d'informations.
from numpy import pi
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()
# Load the Runtime primitive and session
from qiskit_ibm_runtime import (
Batch,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
# Use the least busy backend
backend = service.least_busy(min_num_qubits=127)
print(backend.name)
ibm_sherbrooke
Si un·e étudiant·e épuise son temps de calcul quantique disponible pendant la leçon, les lignes ci-dessous peuvent être décommentées et utilisées pour configurer un simulateur qui imite partiellement le comportement de bruit de l'ordinateur quantique sélectionné ci-dessus.
# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit_aer.primitives import SamplerV2, EstimatorV2
from qiskit_aer.noise import NoiseModel
# Generate the noise model from the backend properties
noise_model = NoiseModel.from_backend(backend)
noisy_sampler = SamplerV2(options={"backend_options": {"noise_model": noise_model}})
noisy_estimator = EstimatorV2(options={"backend_options": {"noise_model": noise_model}})
Tu te souviens peut-être qu'un état propre d'un opérateur, Z, n'est pas un état propre d'un autre opérateur X. Nous allons l'observer maintenant, expérimentalement, en effectuant des mesures le long des axes et . Pour la mesure le long de , nous utilisons simplement qc.measure(), car les ordinateurs quantiques IBM sont structurés pour mesurer le long de . Mais pour mesurer le long de , nous devons faire pivoter le système pour déplacer effectivement l'axe vers l'orientation le long de laquelle nous mesurons. Cela s'accomplit avec une porte Hadamard. Une étape similaire est requise pour les mesures le long de . Les étapes nécessaires sont rassemblées ici pour commodité :
- Pour mesurer le long de :
qc.measure() - Pour mesurer le long de :
qc.h()puisqc.measure() - Pour mesurer le long de :
qc.sdg(),qc.h(),qc.spuisqc.measure()
Étape 1 : Mapper les entrées classiques vers un problème quantique
Dans ce cas, l'étape de mapping consiste simplement à exprimer les mesures et les rotations décrites ci-dessus dans un circuit quantique :
# Step 1: Map
# Import some general packages
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Add a first measurement
qc.measure(qr, cr[0])
qc.barrier()
# Change basis so that measurements made on quantum computer which normally tell us about z, now tell us about x.
qc.h(qr)
# Add a second measurement
qc.measure(qr, cr[1])
qc.draw("mpl")
Étape 2 : Optimiser le problème pour l'exécution quantique
Cette étape prend les opérations que nous voulons effectuer et les exprime en termes de fonctionnalités d'un ordinateur quantique spécifique. Elle mappe également notre problème sur la topologie de l'ordinateur quantique.
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
Étape 3 : Exécuter à l'aide des primitives Qiskit Runtime
Nous pouvons utiliser le Sampler pour collecter des statistiques sur les mesures. Nous allons construire la primitive Sampler pour s'exécuter sur un vrai ordinateur quantique en utilisant mode = backend. Il existe d'autres modes pour d'autres flux de travail, et nous en utiliserons un ci-dessous. Le Sampler sera utilisé en appelant sa méthode run() avec une liste de « pubs » (Primitive Unified Blocs). Chaque pub contient jusqu'à trois valeurs qui, ensemble, définissent une unité de travail de calcul que l'estimateur doit effectuer : circuits, observables, paramètres. Tu peux également fournir une liste de circuits, une liste d'observables et une liste de paramètres. Pour plus d'informations, lis la Vue d'ensemble des PUBs.
Nous voulons exécuter sur un vrai ordinateur quantique, afin d'effectuer une vraie expérience de physique quantique. Si tu épuises ton temps alloué sur de vrais ordinateurs quantiques, tu peux commenter le code ci-dessous pour l'ordinateur quantique, et décommenter le code pour l'exécution sur un simulateur.
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
Étape 4 : Post-traitement
C'est un cas particulièrement simple de post-traitement, dans lequel nous nous contentons de visualiser les comptages.
Note que Qiskit ordonne les qubits, les mesures et d'autres éléments en listant l'élément de numéro le plus bas en dernier / à droite, une convention appelée « little-endian ». Cela signifie que la colonne ci-dessous intitulée « 10 » fait référence aux comptages où la première mesure a donné un « 0 », et la deuxième mesure a donné un « 1 ».
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Si cette convention ne te convient pas, tu peux utiliser marginal_counts pour visualiser les résultats de chaque mesure séparément :
from qiskit.result import marginal_counts
plot_histogram(
marginal_counts(counts, indices=[0]), title="Counts after first measurement"
)
plot_histogram(
marginal_counts(counts, indices=[1]), title="Counts after second measurement"
)
Par défaut, les états dans Qiskit sont initialisés à l'état . Il n'est donc pas surprenant que presque toutes les premières mesures aient donné . Remarque cependant qu'il y avait presque un partage égal dans la deuxième mesure (celle qui donne des informations sur les projections de l'état sur ). Il semble que cet état qui nous donne un résultat très prévisible pour les mesures le long de nous donne un ensemble de résultats très imprévisibles pour les mesures le long de . Explorons cela.
Que se passe-t-il si on effectue les mesures dans l'ordre inverse ? On pourrait commencer par utiliser la porte Hadamard pour obtenir des statistiques sur la probabilité que soit mesuré dans . Puis, pour la deuxième mesure, nous reviendrons à la base en utilisant une deuxième porte Hadamard.
# Step 1:
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Change basis to measure along x.
qc.h(qr)
qc.measure(qr, cr[0])
qc.barrier()
# Change our basis back to z and make a second measurement
qc.h(qr)
qc.measure(qr, cr[1])
qc.draw("mpl")
# Step 2: Transpile the circuit for running on a quantum computer
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Ici, nous semblons avoir encore moins de prévisibilité ! Précédemment, nous connaissions au moins le résultat de la première mesure, maintenant nous avons une distribution assez uniforme sur tous les états possibles. Ce n'est pas trop difficile à comprendre. Nous avons commencé dans , qui est un mélange 50-50 de et , selon Il devrait donc clairement y avoir une probabilité égale d'obtenir l'état + ou - (mappé à 0 et 1 dans le graphique) pour la première mesure. La mesure le long de projette l'état vers soit un état propre soit l'état propre . Chacun de ces états est un mélange 50-50 de et , selon Donc une fois que le système est dans un état propre de , clairement, les mesures le long de donneront à la fois et , et ce avec une probabilité approximativement égale. Notre premier exemple nous a donc montré que certains états auront des résultats très prévisibles pour certaines mesures, mais des résultats imprévisibles pour d'autres mesures. L'exemple actuel nous montre que nous pouvons faire pire que cela. Il existe des états qui peuvent nous donner des résultats imprévisibles pour les deux mesures, même si tout ce que nous faisons est d'échanger l'ordre des mesures. Étudions à quel point une grandeur est certaine ou incertaine pour un état donné.
Calculer l'incertitude
Nous pouvons quantifier cela à l'aide de l'incertitude, ou de la variance. L'« incertitude » est souvent définie comme la racine carrée de la « variance » d'une distribution. Autrement dit, l'incertitude pour une observable est notée et est donnée par
Pour le cas des matrices de Pauli, pour lesquelles , cela devient
Appliquons cela à un exemple concret. Partons de l'état et déterminons l'incertitude de l'observable dans cet état.
Vérifie ta compréhension
Lis la question ci-dessous, réfléchis à ta réponse, puis clique sur le triangle pour révéler la solution.
Calcule l'incertitude de dans l'état , à la main.
Réponse :
Dans l'état donné, cela donne :
Nous pouvons créer un état initial arbitraire avec qc.initialize(). Note que la syntaxe pour l'unité imaginaire ici est .
# Step 1: Map the problem into a quantum circuit
from qiskit.quantum_info import SparsePauliOp
import numpy as np
obs = SparsePauliOp("X")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)
-0.02408454165642664
Selon notre équation ci-dessus, Restons dans le même état, mais trouvons maintenant la valeur d'espérance de :
# Step 1: Map the problem into a quantum circuit
obs = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state to |+>_y
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run(pubs)
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)
0.04958271968581247
Nous pourrions faire les mêmes calculs qu'auparavant, mais nous verrions que la variance est encore très proche de 1.0. On pourrait conclure que . C'est en effet approximativement correct pour l'état que nous avons choisi. Mais peut-on faire mieux ? Ou pire ?
Rappelle-toi qu'il existe une relation d'incertitude entre la position le long d'une direction, et la quantité de mouvement le long de la même direction, Pour ces variables, la forme la plus familière est probablement Si c'est tout ce dont nous nous souvenons, nous pourrions être tentés de penser que et pourraient également avoir une telle limite fondamentale sur l'incertitude. Peut-être est-il impossible que le produit atteigne zéro ? Essayons un autre état et voyons si cela tient. Cette fois, nous utiliserons Voyons ce qui se passe. Note que dans le code ci-dessous, l'estimateur peut accepter deux ensembles de circuits et d'observables dans la même soumission de job.
# Step 1: Map the problem into a quantum circuit
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, obs1_isa), (qc_isa, obs2_isa)]
job = estimator.run(pubs)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc,obs1],[qc,obs2]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print("The expectation value of the first observable is: ", res[0].data.evs)
print("The expectation value of the second observable is: ", res[1].data.evs)
The expectation value of the first observable is: 1.0011036174126302
The expectation value of the second observable is: 0.0029429797670141016
La valeur d'espérance de devrait être proche de 1.0, mais ne devrait pas dépasser 1.0. Ne t'inquiète pas si elle dépasse 1.0 d'une très petite quantité. Cela peut être attribué à des facteurs comme le bruit et/ou les erreurs de lecture. Bien que ce soit un sujet très important, nous pouvons l'ignorer pour l'instant.
Nous avons obtenu une valeur d'espérance de très proche de 1.0 (correspondant à une très faible variance pour ). Cela rend le produit des deux variances assez faible :
Bien que ce ne soit pas exactement zéro, cette valeur devient petite par rapport aux valeurs propres des opérateurs de Pauli (). Tu te souviens peut-être que la relation d'incertitude entre la position linéaire et la quantité de mouvement pouvait s'écrire différemment, en utilisant explicitement la relation de commutation entre les opérateurs et :
où
est le commutateur de et .
C'est la forme qui peut le plus facilement être étendue aux opérateurs de Pauli. En général, pour deux opérateurs et ,
Et dans le cas des matrices de Pauli et , nous avons besoin de pour calculer
Nous montrons cela ici, et laissons des calculs similaires au lecteur comme exercice :
C'est une réponse tout à fait acceptable, mais avec une étape supplémentaire, on voit
Notre relation d'incertitude devient donc
Vérifie ta compréhension
Lis la question ci-dessous, réfléchis à ta réponse, puis clique sur le triangle pour révéler la solution.
Détermine et . Utilise cela pour écrire les relations d'incertitude entre & , et & .
Réponse :
En combinant avec la relation d'incertitude générale, nous obtenons
Vérification de la cohérence
Avant de passer à la suite, vérifions que cela était cohérent avec nos conclusions précédentes. Nous avons utilisé l'état Et nous avons trouvé que Maintenant nous savons que ce produit doit être supérieur ou égal à
En effet, Utilise les questions ci-dessous pour développer ton intuition sur ces résultats :
Vérifie ta compréhension
Lis les questions ci-dessous, réfléchis à tes réponses, puis clique sur les triangles pour révéler les solutions.
Réponds aux éléments suivants ensemble en tant qu'ensemble :
(a) Quels états t'attendrais-tu à avoir une incertitude nulle dans ?
(b) Quels états t'attendrais-tu à avoir une incertitude nulle dans ?
(c) Dans quels états obtiendrais-tu une valeur d'espérance nulle ?
(d) Les réponses aux questions ci-dessus sont-elles cohérentes avec le cas ?
(e) Écris du code pour vérifier cela explicitement en utilisant l'estimateur.
Réponses :
(a) On pourrait s'attendre à ce que les états propres de l'opérateur donnent une incertitude nulle dans . En effet, en utilisant nous avons
(b) On pourrait s'attendre à ce que les états propres de l'opérateur donnent une incertitude nulle dans . En effet, en utilisant nous avons
(c) On s'attend à trouver pour tout état qui, lorsqu'il est mesuré, donne une projection positive sur l'axe aussi souvent qu'une projection négative. Cela inclut les états propres de et .
(d) Oui. On s'attendrait à une très petite valeur pour le produit des incertitudes pour les états propres de ou : Cela peut tenir parce qu'on s'attendrait également à pour ces mêmes états. La relation d'incertitude pourrait donc être satisfaite.
(e) Du code tel que le suivant permettrait de vérifier cela :
obs1 = SparsePauliOp.from_list(
[("X", 1.000)]
)
obs2 = SparsePauliOp.from_list(
[("Y", 1.000)]
)
obs3 = SparsePauliOp.from_list(
[("Z", 1.000)]
)
qc = QuantumCircuit(1,1)
qc.ry(pi/2,0)
job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001)
res=job.result()
Où les résultats retournent toutes les valeurs d'espérance. Pour récupérer toutes les valeurs d'espérance et calculer les incertitudes, nous pourrions utiliser :
xs=res[0].data.evs[0]
ys=abs(res[0].data.evs[1])
zs=res[0].data.evs[2]
import math
prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
Réponds aux éléments suivants ensemble en tant qu'ensemble :
(a) Peux-tu penser à un état dans lequel tu aurais une grande valeur d'espérance ?
(b) T'attendrais-tu à ce que ce même état ait une grande ou petite incertitude dans ?
(c) T'attendrais-tu à ce que ce même état ait une grande ou petite incertitude dans ?
(d) Les réponses aux questions ci-dessus sont-elles cohérentes avec le cas ?
(e) Écris du code pour vérifier cela explicitement en utilisant l'estimateur.
Réponses :
(a) On s'attend à trouver pour l'état propre de : .
(b) On pourrait s'attendre à ce que ait une grande incertitude dans l'état puisque mesurer dans cet état donnerait un résultat positif et négatif avec une fréquence/probabilité égale.
(c) On pourrait s'attendre à ce que ait une grande incertitude dans l'état puisque mesurer dans cet état donnerait un résultat positif et négatif avec une fréquence/probabilité égale.
(d) Oui. On s'attendrait à une grande valeur pour le produit des incertitudes pour les états propres de et pour spécifiquement. On s'attendrait également à pour ce même état. Donc et sont tous deux assez grands dans cet état, et il est plausible que la relation d'incertitude soit à nouveau satisfaite.
(e) Du code tel que le suivant permettrait de vérifier cela :
obs1 = SparsePauliOp.from_list(
[("X", 1.000)]
)
obs2 = SparsePauliOp.from_list(
[("Y", 1.000)]
)
obs3 = SparsePauliOp.from_list(
[("Z", 1.000)]
)
qc = QuantumCircuit(1,1)
qc.rx(-pi/2,0)
job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001)
res=job.result()
Où les résultats retournent toutes les valeurs d'espérance. Pour récupérer toutes les valeurs d'espérance et calculer les incertitudes, nous pourrions utiliser :
xs=res[0].data.evs[0]
ys=abs(res[0].data.evs[1])
zs=res[0].data.evs[2]
import math
prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
Tester les relations d'incertitude
Le test ci-dessus n'a démontré la validité de la relation d'incertitude que pour un seul choix de vecteur d'état . Pour nous convaincre que cela est généralement cohérent avec l'expérience, nous devrions effectuer des calculs similaires avec l'estimateur pour de nombreux choix de vecteur d'état. Commençons par faire pivoter notre vecteur d'état depuis l'axe , en utilisant une porte RY pour produire différents états initiaux à l'aide d'un paramètre .
# The calculation below uses approximately 3-4 minutes of QPU time.
# Step 1: Map the problem into a quantum circuit
from qiskit.circuit import Parameter
import numpy as np
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0>
theta = Parameter("θ")
qc.ry(theta, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()
# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])
# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()
Note que la courbe rouge est toujours supérieure à la courbe orange Parfois le produit d'incertitudes descend et est assez proche de la limite, et d'autres fois il monte et s'en éloigne, mais il respecte toujours la relation d'incertitude.
Bien sûr, ce n'est peut-être pas le meilleur test de la relation d'incertitude, puisque notre limite est toujours très proche de zéro. Utilisons un état quantique qui a une plus grande projection sur les états propres de . Plus précisément, nous allons encore faire pivoter depuis l'axe par des angles variables, mais maintenant nous allons également faire pivoter l'état résultant autour de d'un certain angle, peut-être , et voir ce qui se passe.
# The calculation below uses approximately 3-4 minutes of QPU time.
from qiskit.circuit import Parameter
import numpy as np
# Step 1: Map the problem to a quantum circuit
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0> along one plane, and then along a transverse direction.
theta = Parameter("θ")
qc.ry(theta, 0)
qc.rz(pi / 4, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()
# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])
# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()
Maintenant on voit que la limite sur l'incertitude est mise à l'épreuve ! La courbe rouge se rapproche beaucoup plus de la courbe orange qu'auparavant. En fait, en l'absence de bruit, la relation d'incertitude serait exactement saturée () en un point. En présence de bruit et d'erreurs de lecture, il ne devrait pas être surprenant qu'une exécution donne parfois légèrement supérieur à Ce n'est pas une vraie violation de l'incertitude ; c'est juste un artefact d'une erreur non nulle.
Vérifie ta compréhension
Lis les questions ci-dessous, réfléchis à tes réponses, puis clique sur les triangles pour révéler les solutions.
Explique comment tu pousserais cela à la limite absolue, en rendant aussi grand que possible ?
Réponse :
Le code contient actuellement des lignes qui font pivoter l'état initial par défaut , vers le bas depuis l'axe d'un angle paramétré puis également autour de l'axe d'un angle ce qui fait pivoter le vecteur d'état partiellement vers l'axe .
qc.ry(theta,0)
qc.rz(pi/4,0)
On pourrait changer la rotation autour de de à , en pivotant complètement vers un état propre de :
qc.ry(theta,0)
qc.rz(pi/2,0)
Aucune autre modification ne serait nécessaire.
Modifie le code ou copie-le et implémente cette vérification de la relation d'incertitude avec la valeur d'espérance de Y maximisée. La relation d'incertitude tient-elle ?
Réponse :
Nous utiliserions exactement le code de l'exemple ci-dessus, avec
qc.rz(pi/2,0)
remplacé par
qc.rz(pi/4,0).
La figure résultante devrait ressembler à celle ci-dessous, et oui, le principe d'incertitude devrait toujours être valide.

Modifie le code ci-dessus pour faire une image similaire, démontrant qu'à partir des mesures sur l'ordinateur quantique, le produit se comporte comme il le devrait. Choisis n'importe quel ensemble d'états.
Réponse :
Nous utiliserions exactement le code de l'exemple ci-dessus, et en fait nous pourrions utiliser les mêmes résultats que ci-dessus, en utilisant simplement les valeurs d'espérance pour calculer des incertitudes différentes. Par exemple, nous pourrions utiliser
xs=res[0].data.evs[0]
ys=res[0].data.evs[1]
zs=abs(res[0].data.evs[2])
import math
delx = []
dely = []
prodxy=[]
for i in range(len(xs)):
delx.append((1-xs[i]*xs[i])**0.5)
dely.append((1-ys[i]*ys[i])**0.5)
prodxy.append(((1-xs[i]*xs[i])**0.5)*(1-ys[i]*ys[i])**0.5)
et nous pourrions tracer
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r'$\Delta$ X')
plt.plot(params, dely, label=r'$\langle$ Y $\rangle$')
plt.plot(params, zs, label=r'$\Delta$ Z')
plt.plot(params, prodxy, label=r'$\Delta$X $\Delta$Z')
plt.xlabel(r'$\theta$')
plt.ylabel('Expectation/Uncertainty Values')
plt.legend()
plt.show()
Défi : Écris du code pour parcourir de nombreuses valeurs de , tout comme nous avons parcouru de nombreuses valeurs de , et fais un graphique 3D montrant que la relation d'incertitude n'est jamais violée. Choisis n'importe quelles observables.
Questions
Les enseignants peuvent demander des versions de ces notebooks avec les corrigés et des conseils sur leur placement dans les programmes courants en remplissant ce sondage rapide sur la façon dont les notebooks sont utilisés.
Concepts clés :
- Il existe des relations d'incertitude entre de nombreux ensembles d'observables physiques, notamment la position & la quantité de mouvement linéaire, et les composantes du spin.
- Les matrices de Pauli ne commutent pas. C'est un reflet mathématique du fait que toutes les composantes du spin ne peuvent pas être simultanément connues/déterminées.
- L'informatique quantique fait largement usage des opérateurs/matrices de Pauli, il est donc utile de connaître la relation d'incertitude pour les opérateurs de Pauli, ainsi que les opérateurs de spin étroitement liés.
- Une formule générale pour l'incertitude de deux opérateurs et est
- Un état propre d'un opérateur donne une incertitude nulle dans l'observable physique associée à cet opérateur. Même expérimentalement,
- Un état propre d'un opérateur donnera une plus grande incertitude pour un opérateur qui ne commute pas avec .
- Les résultats expérimentaux utilisant un vrai ordinateur quantique confirment l'intuition que nous tirons des représentations matricielles des opérateurs physiques.
Questions V/F :
- V/F On peut simultanément mesurer et , mais pas .
- V/F On peut simultanément mesurer et , mais pas .
- V/F Les opérateurs de position linéaire et de quantité de mouvement linéaire ne commutent pas.
- V/F Les ordinateurs quantiques IBM mesurent le long de par défaut, donc une rotation doit être effectuée pour mesurer le long de toute autre direction.
- V/F Le circuit ci-dessous mesure effectivement puis .
Questions à choix multiples :
-
Le diagramme ci-dessous illustre laquelle des relations d'incertitude suivantes ?
- a.
- b.
- c.
- d. Aucune des réponses ci-dessus

-
Quelle est la séquence standard pour effectuer une mesure le long de ?
- a. Seulement
qc.measure() - b.
qc.h()puisqc.measure() - c.
qc.h(),qc.h()puisqc.measure() - d.
qc.h(),qc.s,qc.h()puisqc.measure() - e.
qc.sdg(),qc.h(),qc.spuisqc.measure() - f.
qc.sdg(),qc.h(),qc.s,qc.h()puisqc.measure()
- a. Seulement
-
Lequel des états suivants donne la plus grande valeur d'espérance ?
- a.
- b.
- c. aussi appelé
- d. aussi appelé
- e. aussi appelé
- f. aussi appelé
-
Lequel des états suivants donne la plus grande incertitude ?
- a.
- b. aussi appelé
- c. aussi appelé
- d. a et b sont à égalité
- e. b et c sont à égalité
- f. a, b et c sont à égalité
Questions de discussion :
-
Ce concept d'incertitude entre-t-il en conflit avec la notion de spin comme une flèche vectorielle dans l'espace cartésien ? Et sur la sphère de Bloch ?
-
Suppose que tu orientes un dispositif de mesure dans une direction à mi-chemin entre les axes et . Que se passe-t-il ? Peux-tu effectuer une mesure dans cette direction ? Comment cela est-il lié à l'incertitude dans et ?
-
Quelles expériences supplémentaires voudrais-tu réaliser pour te convaincre des résultats obtenus ici ?