Aller au contenu principal
Ce projet est en phase bêta. Tu as trouvé un bug ? Ouvrir un ticket GitHub. Une question ou une idée ? Pose ta question dans Discussions — tes retours sont les bienvenus !
Quelle est la qualité de la traduction sur cette page ?

Spécifier des observables dans la base de Pauli

Versions des packages

Le code de cette page a été développé avec les dépendances suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

qiskit[all]~=2.5.2

En mécanique quantique, les observables correspondent à des propriétés physiques mesurables. Lorsqu'on considère un système de spins, par exemple, on peut être intéressé par la mesure de l'énergie du système ou par l'obtention d'informations sur l'alignement des spins, comme la magnétisation ou les corrélations entre spins.

Pour mesurer une observable OO à nn qubits sur un ordinateur quantique, tu dois la représenter comme une somme de produits tensoriels d'opérateurs de Pauli, c'est-à-dire

O=∑k=1KαkPk,  Pk∈{I,X,Y,Z}⊗n,  αk∈R,O = \sum_{k=1}^K \alpha_k P_k,~~ P_k \in \{I, X, Y, Z\}^{\otimes n},~~ \alpha_k \in \mathbb{R},

où

I=(1001)  X=(0110)  Y=(0−ii0)  Z=(100−1)I = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} ~~ X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} ~~ Y = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix} ~~ Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}

et on utilise le fait qu'une observable est hermitienne, c'est-à-dire O†=OO^\dagger = O. Si OO n'est pas hermitienne, elle peut quand même être décomposée en somme de Paulis, mais le coefficient αk\alpha_k devient complexe.

Dans de nombreux cas, l'observable est naturellement spécifiée dans cette représentation après avoir associé le système étudié à des qubits. Par exemple, un système de spin-1/2 peut être décrit par un hamiltonien d'Ising

H=∑⟨i,j⟩ZiZj−∑i=1nXi,H = \sum_{\langle i, j\rangle} Z_i Z_j - \sum_{i=1}^n X_i,

où les indices ⟨i,j⟩\langle i, j\rangle parcourent les spins en interaction et les spins sont soumis à un champ transverse en XX. L'indice inférieur indique sur quel qubit agit l'opérateur de Pauli, c'est-à-dire que XiX_i applique un opérateur XX sur le qubit ii et laisse les autres inchangés.

Dans le SDK Qiskit, cet hamiltonien peut être construit avec le code suivant.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit.quantum_info import SparsePauliOp

# define the number of qubits
n = 12

# define the single Pauli terms as ("Paulis", [indices], coefficient)
interactions = [
("ZZ", [i, i + 1], 1) for i in range(n - 1)
] # we assume spins on a 1D line
field = [("X", [i], -1) for i in range(n)]

# build the operator
hamiltonian = SparsePauliOp.from_sparse_list(
interactions + field, num_qubits=n
)
print(hamiltonian)
SparsePauliOp(['IIIIIIIIIIZZ', 'IIIIIIIIIZZI', 'IIIIIIIIZZII', 'IIIIIIIZZIII', 'IIIIIIZZIIII', 'IIIIIZZIIIII', 'IIIIZZIIIIII', 'IIIZZIIIIIII', 'IIZZIIIIIIII', 'IZZIIIIIIIII', 'ZZIIIIIIIIII', 'IIIIIIIIIIIX', 'IIIIIIIIIIXI', 'IIIIIIIIIXII', 'IIIIIIIIXIII', 'IIIIIIIXIIII', 'IIIIIIXIIIII', 'IIIIIXIIIIII', 'IIIIXIIIIIII', 'IIIXIIIIIIII', 'IIXIIIIIIIII', 'IXIIIIIIIIII', 'XIIIIIIIIIII'],
coeffs=[ 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j,
1.+0.j, 1.+0.j, 1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,
-1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j])

Si on souhaite mesurer l'énergie, l'observable est l'hamiltonien lui-même. Sinon, on peut être intéressé par la mesure des propriétés du système, comme la magnétisation moyenne, en comptant le nombre de spins alignés dans la direction ZZ avec l'observable

O=1n∑i=1ZiO = \frac{1}{n} \sum_{i=1} Z_i

Pour les observables qui ne sont pas données en termes d'opérateurs de Pauli mais sous forme matricielle, il faut d'abord les reformuler dans la base de Pauli afin de les évaluer sur un ordinateur quantique. On peut toujours trouver une telle représentation, car les matrices de Pauli forment une base pour les matrices hermitiennes 2n×2n2^n \times 2^n. On développe l'observable OO comme suit :

O=12n∑P∈{I,X,Y,Z}⊗nTr(OP)P,O = \frac{1}{2^n} \sum_{P \in \{I, X, Y, Z\}^{\otimes n}} \mathrm{Tr}(O P) P,

où la somme parcourt tous les termes de Pauli nn-qubit possibles et Tr(⋅)\mathrm{Tr}(\cdot) est la trace d'une matrice, qui joue le rôle de produit scalaire. Le facteur 1/2n1/2^n tient compte de la normalisation de Hilbert-Schmidt des chaînes de Pauli à nn qubits. Tu peux implémenter cette décomposition d'une matrice en termes de Pauli en utilisant la méthode SparsePauliOp.from_operator, comme ceci :

import numpy as np
from qiskit.quantum_info import SparsePauliOp

matrix = np.array(
[[-1, 0, 0.5, -1], [0, 1, 1, 0.5], [0.5, 1, -1, 0], [-1, 0.5, 0, 1]]
)

observable = SparsePauliOp.from_operator(matrix)
print(observable)
SparsePauliOp(['IZ', 'XI', 'YY'],
coeffs=[-1. +0.j, 0.5+0.j, 1. -0.j])

Cela signifie que la matrice peut s'écrire en termes de Pauli comme O=−Z1+0.5X2+Y2Y1O = -Z_1 + 0.5 X_2 + Y_2 Y_1.

remarque

Rappelle-toi que l'ordre du produit tensoriel correspond aux qubits selon qn⊗qn−1⊗⋯⊗q1q_n \otimes q_{n-1} \otimes \cdots \otimes q_1.

remarque

Si l'observable est hermitienne (c'est-à-dire O†=OO^\dagger = O), les coefficients de Pauli sont des nombres réels. On peut cependant aussi décomposer n'importe quelle autre matrice complexe en termes de Paulis, si l'on autorise des coefficients à valeurs complexes.

Mesurer dans les bases de Pauli​

Une mesure projette l'état d'un qubit sur la base computationnelle {∣0⟩,∣1⟩}\{|0\rangle, |1\rangle\}. Cela implique que tu peux uniquement mesurer des observables qui sont diagonales dans cette base, comme les Paulis composés uniquement de termes II et ZZ. Mesurer des termes de Pauli arbitraires nécessite donc un changement de base pour les diagonaliser. Pour ce faire, effectue les transformations suivantes :

X→Z=HXHY→Z=HS†YSH,\begin{aligned} X &\rightarrow Z = H X H \\ Y &\rightarrow Z = H S^\dagger Y S H, \end{aligned}

où HH est la porte Hadamard et S=ZS = \sqrt{Z} est parfois appelée la porte de phase. Si tu utilises un Estimator pour calculer des valeurs d'espérance, les transformations de base sont effectuées automatiquement.

Voici un exemple illustrant comment préparer un circuit quantique et mesurer manuellement le qubit 0 dans la base X, le qubit 1 dans la base Y et le qubit 2 dans la base Z. On applique les transformations montrées dans l'équation précédente et on obtient le circuit suivant :

from qiskit.circuit import QuantumCircuit

# create a circuit, where we would like to measure
# q0 in the X basis, q1 in the Y basis and q2 in the Z basis
circuit = QuantumCircuit(3)
circuit.ry(0.8, 0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.barrier()

# diagonalize X with the Hadamard gate
circuit.h(0)

# diagonalize Y with Hadamard as S^\dagger
circuit.sdg(1)
circuit.h(1)

# the Z basis is the default, no action required here

# measure all qubits
circuit.measure_all()
circuit.draw("mpl")

Sortie de la cellule de code précédente

Étapes suivantes​

Recommandations